package com.example.nestedclassdemo;
/**
* 匿名内部类
* - 没有正式类名的内部类
* - 编译器产生内部名字: 类名+$+数字编号
* - 没有类名,没有构造函数,能用父类/父接口的构造函数(可带参数)
* - 可以继承,改写,补充父类/父接口的方法
* - 内部不可以新定义静态成员(变量+方法),常量除外
* - final static int a = 5;
* - 可以访问外部包围类的成员变量和方法(包括private)
* - 如果定义在静态方法中,也只能访问外部包围类的静态成员
* - 没有类名,外部包围类和其他类也无法访问到匿名内部类
*/
public class Outer1 {
private String name = "abc";
public void f1(){
String name = "def";
Runnable r = new Runnable() {
//匿名内部类不能定义静态变量,除非是常量
public final static int a = 5;
//public static int b = 3;
String name = "ghi";
@Override
public void run() {
System.out.println("hello "+name);
}
//静态方法不能在匿名内部类定义
//public static void f2(){}
};
new Thread(r).start();
System.out.println(r.getClass().getName());
//编译后会产生第二个class匿名内部类
Runnable r2 = new Runnable() {
@Override
public void run() {
System.out.println("hello "+Outer1.this.name);
}
};
new Thread(r2).start();
System.out.println(r2.getClass().getName());
}
}
package com.example.nestedclassdemo;
import java.io.Serializable;
/**
* 局部内部类: Local classes
* - 编译后名称: 外部类名+$+序号+内部类名
* - 可以继承其他类,或者实现其他接口
* - 非静态的类,不能包含静态成员(变量和方法),除了常量
* - 可以访问外部包围类的成员
* - 如果定义在静态方法中,只能访问包围类的静态成员
* - 局部内部类不能是一个接口,即接口不能定义在代码块中
*/
public class Outer2 {
String name = "abc";
//局部内部类
public void f1(){
String name = "def";
class Inner2 extends Outer1 implements Runnable, Serializable {
final static int a = 1;
//不允许定义静态普通类成员
//static int b = 2;
String name = "ghi";
public void f2(){
System.out.println(name);
System.out.println(Outer2.this.name);
}
@Override
public void run() {
System.out.println(name);
}
}
Inner2 obj1 = new Inner2();
obj1.f2();
System.out.println(obj1.getClass().getName());
}
//局部内部类
public static void f2(){
final String name = "def";
class Inner2{
public String f2(){
return "this is f2()";
}
}
Inner2 inner2 = new Inner2();
String s = inner2.f2();
System.out.println(s);
System.out.println(inner2.getClass().getName());
}
}
package com.example.nestedclassdemo.shadow;
public class ShadowTest {
public int x = 0;
class FirstLevel{
public int x = 1;
void methodInFirstLevel(int x){
System.out.println("x = "+x); //line 10 x
System.out.println("this.x = "+this.x); //line 8 x
System.out.println("ShadowTest.this.x = "+ShadowTest.this.x); //line 5 x
}
}
public static void main(String... args){
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel f1 = st.new FirstLevel();
f1.methodInFirstLevel(20);
}
}
package com.example.nestedclassdemo.shadow;
public class ShadowTest2 {
public int x = 0;
public void f1(){
//局部内部类无法访问得到!
int x = 20;
class FirstLevel{
public int x = 1;
void methodInFirstLevel(int x){
System.out.println("x = "+x); //line 14 x
System.out.println("this.x = "+this.x); //line 12 x
System.out.println("ShadowTest.this.x = "+ShadowTest2.this.x); //line 5 x
}
}
FirstLevel obj = new FirstLevel();
obj.methodInFirstLevel(10);
}
public static void main(String... args) {
ShadowTest2 st = new ShadowTest2();
st.f1();
}
}
package com.example.nestedclassdemo.shadow;
public class ShadowTest3 {
public int x = 0;
public void f1(){
//可以访问得到,没有被遮蔽!
int x = 20;
class FirstLevel{
void methodInFirstLevel(){
System.out.println("x = "+x);//line 9 x
System.out.println("ShadowTest3.this.x = "+ShadowTest3.this.x); //line 5 x
}
}
//x=30;
FirstLevel obj = new FirstLevel();
obj.methodInFirstLevel();
}
public static void main(String... args) {
ShadowTest3 st = new ShadowTest3();
st.f1();
}
}
package com.example.nestedclassdemo.outer3;
public class Animal {
String name;
}
package com.example.nestedclassdemo.outer3;
public interface Flyable {
void fly();
}
package com.example.nestedclassdemo.outer3;
/**
* 普通内部类
* - 编译后名称: 外部类名+$+内部类名
* - 可以继承其他类,或者实现其他接口
* - 可以用private/package private(不写)/protected/public控制外界访问
* - 非静态的类,不能包含静态变量/方法,除了常量
* - 和外部包围类的实例相关,一个普通内部类实例肯定是在一个外部包围类的实例中,
* 且可以访问外部包围类的所有成员
* - 在第三方类中,需要先创建外部包围类实例,才能创建普通内部类的实例,
* 不允许单独的普通内部类对象存在!!!
*/
public class Outer3 {
String name = "aaaaaa";
public class Bird extends Animal implements Flyable{
//常量OK
public static final int a = 3;
//不能定义非常量的static变量
//public static int b = 4;
@Override
public void fly() {
System.out.println(Outer3.this.name+" can fly");
}
}
public Bird b1 = new Bird();
public void f1(){
b1.fly();
System.out.println(b1.getClass().getName());
this.name = "bbbbbb";
b1.fly();
}
public Bird getBird(){
return this.b1;
}
}
package com.example.nestedclassdemo.outer3;
public class Outer3Test {
public static void main(String[] args) {
Outer3 foo1 = new Outer3();
foo1.f1();
Outer3.Bird foo2 = foo1.new Bird();
foo2.fly();
System.out.println(foo2 == foo1.getBird());
//foo1对象下,有2个内部类对象和它关联
//不允许没有关联的单独的普通内部类对象
//Outer3.Bird foo3 = new Outer3().Bird();
}
}
package com.example.nestedclassdemo.outer4;
/**
* 静态嵌套类的语法总结
* - 需要加修饰符static
* - 可以定义静态成员和非静态成员
* - 不能直接访问包围类的非静态成员,可直接访问包围类的静态成员
* = 可通过包围类的对象进行访问非静态成员
* - 外界可以通过静态嵌套类名访问其静态成员,通过对象访问其非静态成员
* - 外界需要通过包围类才可以访问到静态嵌套类,并创建其对象,不需要外部包围类的实例
*/
public class Outer4 {
private String outField1 = "outer 111";
private static String outStaticField2 = "outer static 222";
/**
* 静态嵌套类
*/
public static class Inner4{
//静态嵌套类可以定义静态和非静态成员
private String innField1 = "inner 333";
static String innStaticField2 = "inner static 444";
public void innFun1(){
//静态嵌套类可以直接访问包围类的静态成员
System.out.println(innField1);
//System.out.println(Outer4.outField1);
System.out.println(Outer4.outStaticField2);
System.out.println(outStaticField2);
//静态嵌套类可以通过对象访问包围类的非静态成员
Outer4 outObj = new Outer4();
System.out.println(outObj.getOutField1());
}
public String getInnField1(){
return this.innField1;
}
public static String getInnStaticField2(){
hello();
return innStaticField2;
}
public static void hello(){
System.out.println("inner hello");
}
}
public String getOutField1(){
return this.outField1;
}
public static void outFun2(){
Inner4 obj1 = new Inner4();
Inner4 obj2 = new Inner4();
System.out.println(obj1==obj2);//false
System.out.println(obj1.getInnField1());
System.out.println(Inner4.getInnStaticField2());
}
public static void hello(){
System.out.println("outer hello");
}
}
package com.example.nestedclassdemo.outer4;
public class Outer4Test {
public static void main(String[] args) {
//第三方类访问静态嵌套类
Outer4.Inner4 obj1 = new Outer4.Inner4();
String innField1 = obj1.getInnField1();
System.out.println("innField1:"+innField1);
Outer4.Inner4 obj2 = new Outer4.Inner4();
System.out.println(obj1==obj2);
System.out.println("====================");
Outer4 obj3 = new Outer4();
Outer4.outFun2();
}
}