public class Exercise7 { static int x, y, z; static { int x = 5; x--; } static { x--; } public static void main(String[] args) { System.out.println("x=" + x); z--; method(); System.out.println("result:" + (z + y + ++z)); } public static void method() { y = z++ + ++z; }}
答案
public class Exercise7 { static int x, y, z; static { int x = 5; // 局部变量“遮蔽”成员变量:变量寻找优先级 x--; } static { x--; // -1 } public static void main(String[] args) { System.out.println("x=" + x); // -1 z--; // -1 method(); System.out.println("result:" + (z + y + ++z)); // 1 + 0 + 2 = 3 } public static void method() { y = z++ + ++z; // y = -1(z=0) + 1(z=1) = 0 }}
static 成员变量
public class Exercise8 { public static void main(String[] args) { System.out.println(new SDText().x + "," + new SDText().y + "," + new SDText().x); }}class SDText { static SDText sd = new SDText(); static int x = 3; static int y; public SDText() { x++; y++; }}
答案
4,3,6
new SDText().x static SDText sd = new SDText(); // x = 1, y = 1 static int x = 3; // x = 3, y = 1 public SDText() // x = 4, y = 2new SDText().y // x = 5, y = 3new SDText().x // x = 6, y = 4
static 成员变量:
什么时候创建?
共享(就一份)
类初始化流程
public class T { public static int k = 0; public static T t1 = new T("t1"); public static T t2 = new T("t2"); public static int i = print("i"); public static int n = 99; public int j = print("j"); { print("构造块"); } static { print("静态块"); } public T(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; ++i; } public static int print(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; return ++i; } public static void main(String[] args) {}}
class HelloA { public HelloA() { System.out.println("HelloA"); } { System.out.println("I'm A Class"); } static { System.out.println("static A"); }}public class HelloB extends HelloA { public HelloB() { System.out.println("HelloB"); } { System.out.println("I'm B Class"); } static { System.out.println("static B"); } public static void main(String[] args) { new HelloB(); }}
答案
static Astatic BI'm A ClassHelloAI'm B ClassHelloB
父类 HelloA 装载:System.out.println("static A");子类 HelloB 装载:System.out.println("static B");new HelloB():对象创建1. 父类 HelloA <init>()代码块:System.out.println("I'm A Class");构造器:System.out.println("HelloA");2. 子类 HelloB <init>()System.out.println("I'm B Class");System.out.println("HelloB");
实例初始化与函数重写
public class Exercise13 { public static void main(String[] args) { Sub s = new Sub(); }}class Base { Base() { method(100); } { System.out.println("base"); } public void method(int i) { System.out.println("base : " + i); }}class Sub extends Base { Sub() { super.method(70); } { System.out.println("sub"); } public void method(int j) { System.out.println("sub : " + j); }}
答案
basesub : 100subbase : 70
对象创建:1. 父对象:Base<init>() 1. 代码块:base 2. method(100):创建的是子类,调用子类重写的方法:sub : 100 这里看创建的哪个类,是看运行时类型,即:new Sub(); 而不是看编译是类型:Sub s = 所以即使这里改成:Base s = new Sub(),依然调 Sub 重写的方法1. 子对象:Sub<init>() 1. 代码块:sub 2. super.method(70):调父类方法:base : 70
类初始化与实例初始化 2
public class Exercise14 { public static void main(String[] args) { Son son = new Son(); }}class Father { static { System.out.println("(1)父类的静态代码块"); } { System.out.println("(2)父类的非静态代码块"); } Father() { System.out.println("(3)父类的无参构造"); }}class Son extends Father { static { System.out.println("(4)子类的静态代码块"); } { System.out.println("(5)子类的非静态代码块"); } Son() { System.out.println("(6)子类的无参构造"); }}
public class Exercise15 { public static void main(String[] args) { Zi zi = new Zi(); }}class Fu { private static int i = getNum("(1)i"); private int j = getNum("(2)j"); static { print("(3)父类静态代码块"); } { print("(4)父类非静态代码块,又称为构造代码块"); } Fu() { print("(5)父类构造器"); } public static void print(String str) { System.out.println(str + "->" + i); } public static int getNum(String str) { print(str); return ++i; }}class Zi extends Fu { private static int k = getNum("(6)k"); private int h = getNum("(7)h"); static { print("(8)子类静态代码块"); } { print("(9)子类非静态代码块,又称为构造代码块"); } Zi() { print("(10)子类构造器"); } public static void print(String str) { System.out.println(str + "->" + k); } public static int getNum(String str) { print(str); return ++k; }}
类装载:父:private static int i = getNum("(1)i"); print(str); // (1)i -> 0 return ++i; // 即:i = ++i // i = 1static {print("(3)父类静态代码块");} print(str); // (3)父类静态代码块 -> 1子:private static int k = getNum("(6)k"); print(str); // (6)k -> 0 return ++k; // 即:k = ++k // k = 1static {print("(8)子类静态代码块");} print(str); // (8)子类静态代码块 -> 1对象创建:Zi zi = new Zi();父 <init>():private int j = getNum("(2)j"); print(str); // (2)j -> 1 return ++i; // i = 2, j = 2{print("(4)父类非静态代码块,又称为构造代码块");} print(str); // (4)父类非静态代码块,又称为构造代码块 -> 2Fu() {print("(5)父类构造器");} print(str); // (5)父类构造器 -> 2子 <init>():private int h = getNum("(7)h"); print(str); // (7)h -> 1 return ++k; // k = 2, h = 2{print("(9)子类非静态代码块,又称为构造代码块");} print(str); // (9)子类非静态代码块,又称为构造代码块 -> 2Zi() {print("(10)子类构造器");} print(str); // (10)子类构造器 -> 2
调用运行时类型的重写方法 1
public class Exercise16 { public static void main(String[] args) { Son s1 = new Son(); }}class Father { private int a = getNumber(); { System.out.println("Father非静态代码块 a = " + a); } Father() { System.out.println("Father()无参构造"); } public int getNumber() { System.out.println("Father:getNumber()"); return 1; }}class Son extends Father { { System.out.println("Son非静态代码"); } public Son() { System.out.println("Son():无参构造"); } public int getNumber() { System.out.println("Son:getNumber()"); return 2; }}
父对象创建:private int a = getNumber(); // 创建的是 new Son(); 调 Son 重写的 getNumber() 方法 // Son:getNumber() return 2; // a = 2代码块:// Father非静态代码块 a = 2构造函数:// Father()无参构造子对象创建:代码块:// Son非静态代码构造函数:// Son():无参构造
调用运行时类型的重写方法 2
public class Exercise17 { public static void main(String[] args) { Base s = new Sub(); }}class Base { Base() { this.method(100); } { System.out.println("base"); } public void method(int i) { System.out.println("base : " + i); }}class Sub extends Base { Sub() { super.method(70); } { System.out.println("sub"); } public void method(int j) { System.out.println("sub : " + j); }}
父对象创建:代码块:// base构造函数:// sub : 100// 运行时类型:new Sub();,调 Sub 重写的方法// 和编译时类型 Base s = 无关子对象创建:代码块:// sub构造函数:// base : 70// 显式调的 super
final 修饰引用类型
public class TestOther { public static void main(String[] args) { Other o = new Other(); new TestOther().addOne(o); /* (1)new TestOther():匿名对象,作用是为了调用 addOne 方法。 (2)上面的实参 o,把 Other 对象的地址值,传给了下面的 addOne 方法的形参 o (3)下面的 addOne 方法的形参 o,前面有一个 final 修饰, 这个 final 在这里的意思是,形参 o 不能够指向新的对象, 这就意味着,形参和实参此时一定是指向同一个对象。 (4)如果形参和实参指向同一个对象,那么形参对象属性值的修改,其实就是实参对象属性值的修改 */ System.out.println(o.i); // 1 } public void addOne(final Other o){ // o = new Other(); //错误,o 不能重新赋值 o.i++; // 没改 o,o.i 不是 final,可以改 }}class Other { public int i; // 如果 i 前面有 final,才是表示 i 的值不能被修改}
属性冲突
interface A { int x = 0;}class B { int x = 1;}public class C extends B implements A { public void printX() { System.out.println(x); } public static void main(String[] args) { new C().printX(); }}
答案
属性冲突没有类优先原则,必须显式指明是调哪个
public void printX() { System.out.println(x); // 报错:有歧义 // 必须显式指明:super.x 或 A.x // 注意:不能将 super.x 写成 B.x,B.x 表示 B 的静态属性 x}
默认方法冲突 1
类优先原则
“默认”的含义:没有就用我默认的,有了就不用默认的了
interface A { default void print() { System.out.println("interface A"); }}class B { public void print() { System.out.println("class B"); }}public class C extends B implements A { public static void main(String[] args) { new C().print(); // class B }}
默认方法冲突 2
interface A { default void print() { System.out.println("interface A"); }}class B { public void print() { System.out.println("class B"); }}public class C extends B implements A { public void print() { // 子类完全重写 System.out.println("class C"); // 调父类 super.print(); // 调接口默认方法 A.super.print(); } public static void main(String[] args) { new C().print(); }}
Ball.java:13: error: types Playable and Bounceable are incompatible;public class Ball implements Playable, Bounceable { ^ class Ball inherits unrelated defaults for play() from types Playable and Bounceable1 error
局部内部类
public class Exercise36 { public static void main(String[] args) { Out out = new Out(); out.Print(3); }}class Out { private int age = 12; public void Print(final int x) { class In { public void inPrint() { System.out.println(x); // 3 System.out.println(age); // 12 } } new In().inPrint(); }}
同名变量访问
public class Exercise37 { public static void main(String[] args) { Out.In in = new Out().new In(); in.print(); }}class Out { private int age = 12; class In { private int age = 13; public void print() { int age = 14; System.out.println("局部变量:" + age); // 14 System.out.println("内部类变量:" + this.age); // 13 System.out.println("外部类变量:" + Out.this.age); // 12 } }}
非 static 内部类只能由对象 new
public class Exercise38 { public Exercise38() { Inner s1 = new Inner(); s1.a = 10; Inner s2 = new Inner(); s2.a = 20; Exercise38.Inner s3 = new Exercise38.Inner(); // 和上面是一样的,都是 this 调的 System.out.println(s3.a); } class Inner { public int a = 5; } public static void main(String[] args) { Exercise38 t = new Exercise38(); Inner r = t.new Inner(); System.out.println(r.a); }}
包装类缓存
public static void main(String[] args) { Integer i1 = 128; Integer i2 = 128; int i3 = 128; int i4 = 128; System.out.println(i1 == i2); System.out.println(i3 == i4); System.out.println(i1 == i3); double a = 2.0; double b = 2.0; Double c = 2.0; Double d = 2.0; System.out.println(a == b); System.out.println(c == d); System.out.println(a == d);}