static
編寫一個類時,只有透過 new
關鍵字才會產生出物件,此時系統才會分配記憶體空間給該物件,這樣才能供外部調用。但某些特定數據在記憶體空間只有一份。台灣是個國家名稱,每一個台灣人都共享此國家名稱,不必每一個人的實例都分配一個代表國家名稱的變量。
static
修飾的變量是共享的- 因為
class
只會加載一次,則static
變量在記憶體中也只會存在一份,存在方法區的靜態域 - 靜態方法中,只能調用靜態的方法或屬性,非靜態方法,既可調用非靜態的方法或屬性,也可以調用靜態的方法或屬性
- 在靜態方法內,不能使用
this
、super
關鍵字,生命週期 - 操作靜態屬性的方法,通常設置為
static
- 工具類中的方法,習慣聲名為
static
- 靜態變數隨著類加載而加載,因此早於物件的建立
代碼塊
- 用來初始類和對象
- 有修飾的話只能用
static
- 比較
- 靜態代碼塊
- 內部可以有輸出句
- 隨著類加載而執行,且只執行一次
- 初始化類的訊息
- 如果一個類中定義了多個靜態代碼塊,則按照宣告先後順序執行
- 靜態代碼塊的執行要優先於非靜態代碼塊的執行
- 靜態代碼塊內只調用靜態的屬性、靜態的方法,不能調用非靜態的結構
- 非靜態代碼塊
- 內部可以有輸出句
- 隨著物件的創見而執行
- 每創建一個物件,就執行一次非靜態代碼塊
- 可以在創建對象時,隊對象的屬性等進行初始化
- 如果一個類中定義了多個非靜態代碼塊,則按照宣告先後順序執行
- 非靜態代碼塊內只調用靜態的屬性、靜態的方法,也能調用非靜態的結構
- 靜態代碼塊
public class Person {
String name;
int age;
static String des = "Hello";
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 隨著類加載而執行
static {
System.out.println("Hello Static block");
}
// 隨著物件的建立而執行
{
System.out.println("Hello block");
}
public void eat(){
System.out.print("eat...");
}
public void sleep(){
System.out.print("sleep...");
}
// 隨著類加載而加載
public static void info(){
System.out.print("info...");
}
}
創建抽像類的匿名子類對象
public class PersonTest{
public static void main(String[] args){
method(new Student()); // 匿名物件
Worker worker = new Worker();
method1(worker);// 非匿名的類非匿名的物件
method1(new worker()); // 非匿名的類匿名的物件
Person p = new Person(){ // 創建匿名子類的對象
/**
* 當成子類,只有子類才能覆寫
* */
@Override
public void eat(){
}
@Override
public void breath(){
}
};
}
public static void method1(Person p){
p.eat();
p.walk();
}
public static void method(Student s){
}
}
class Worker extends Prson{
...
...
}
interface
- 有多重繼承效果
- 沒有 is-a 關係,是 has a
- 定義共同的行為特徵
extends
是一個是不是的關係,interface
是能不能的關係interface
本質是契約、標準、規範- 不能定義建構方法,表示無法實例化
- 如果實現類沒有覆蓋 interf`ace 中所有抽象方法。則此實現仍然為一個抽象類
interface
與interface
之間可以繼承,也可以多繼承interface
多態性
interface AA {
}
interface BB {
}
interface CC extends AA, BB {
}
定義的結構
- JDK7
- 只能定義
- 全域常量
- public static final
- 抽象方法
- public abstrace
- 全域常量
- 只能定義
- JDK8
- 全域常量
- 抽象方法
- 靜態方法
- 默認方法
- 等
abstract 和 interface 差異
- 相同
- 不能實例
- 都可被繼承
- 不同
- 抽象有建構方法
interface
不能宣告建構方法- 類,單繼承性
interface
,多繼承性,類interface
多實現
interface 應用
- 代理模式(Proxy)
- 工廠模式
除錯
interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void px(){
System.out.println(x); // 不知道是哪一個
}
public static void main(String[] args){
new C().pX();
}
}
JAVA8 interface
- 靜態方法
static
修飾- 只能藉由
interface
自己調用
- 默認方法
default
修飾- 透過實現類對象調用
- 可以
override
- 如果子類(或實現類)繼承的父類和實現的
interface
聲明同名同參數的方法,那麼子類在沒有重寫此方法下,默認調用的是父類中的- 類優先原則
- 如果實現類實現多個
interface
,而這多個interface
中定義了同名同參的默認方法,那麼實現類沒有重寫此方法的情況下- 接口衝突
public interface CompareA{
public static void method1(){
System.out.println("...");
}
public default void method2(){
System.out.println("...");
}
default void method3(){
System.out.println("...");
}
}
public void myMethod() {
method3();
super.method3();
// 調用 interdace 中默認方法
CompareA.super.method3();
CompareB.super.method3()
}
內部類
類別中的類別
Inner class
一般用在定義他的類或語句區塊之內,在外部引用時必須給出完整的名稱Inner class
的名字不能包含它的外部類類名相同
- 分類
- 成員內部類
static
成員內部類和非static
成員內部類
- 局部內部類
- 匿名內部類
- 方法內
- 代碼區塊內
- 建構方法內
- 成員內部類
- 成員內部類
- 作為外部類成員
- 調用外部類結構
static
修飾- 可被權限修飾
- 作為一個類
- 可聲明屬性、方法、建構方法
- 可被
final
修飾 - 繼承
- 可被
abstract
- 作為外部類成員
- 如何實例化成員內部類
- 如何在成員內部類中區分調用外部類的結構
- 開發中局部內部類的使用
- 編譯後,外部和內部會生成 bytecode 檔案
- 成員內部類
- 外部類$內部類名.class
- 局部內部類
- 外部類$數字 內部類.class
- 成員內部類
public static void main(String [] args) {
Person.Dog dog = new Person.Dog(); // 靜態 Dog 實例
dog.method();
Person p = new Person();
Person.Cat cat = p.new Cat(); // 非靜態實例
cat.method();
}
class Person {
String name;
// 成員內部類
static class Dog {
}
class Cat{
String name;
Person.this.method(); // 調用外部類方法
public void display(String name) {
System.out.println(name); // 參數
System.out.println(this.name); // 內部類
System.out.println(Person.this.name);// 外部類
}
}
public Person(){
class CC {
}
}
public void method() {
class AA {
}
}
{
class BB {
}
}
}
public class InnerClass {
public void method(){
class AA{
}
}
public Comparable getComparable(){
// 局部內部類
class MyComparable implement Comparable{
@Override
public int compareTo(Object o){
return 0;
}
}
return new MyComparable();
}
}
內部類使用注意點
- 在局部內部類的方法中,如果調用局部內部類所聲明的方法中的局部變量,要求該局部變量為 final,jdk 1.7 前都是這樣要求,JAVA 8 之後可省略,預設就是