分享下匿名内部类的案例:
内部类的访问规则
/**
* 内部类的访问规则
* 1.内部类可以直接访问外部类的成员,包括私有
* 2.外部类访问内部类,必须建立内部类的对象
* 3.之所以内部类可以访问外部类,因为内部类中,持有外部类的引用,
* 格式: 外部类名.this
*
* @author mahao
* @date: 2019年2月14日 下午1:10:55
*/
public class InnerClassDemo {
public static void main(String[] args) {
Out out = new Out();
out.method();
//直接获取内部类对象
Out.Inner in = new Out().new Inner();
in.function();
}
}
/**
* 外部类
*/
class Out{
//外部类属性
private String name = "外部类名字";
/**
*内部类
*/
class Inner{
//3.当内部类和外部类有相同属性时,要用this的使用
private String name = "内部类名字";
//1.内部类可以直接访问外部类成员
public void function() {
String name = "名字";
System.out.println("不加this,默认访问方法里面的变量,如果没有,则搜索成员变量:---"+name);
System.out.println("this在这里,是指Inner对象,所以指的是内部类属性:---"+this.name);
System.out.println("内部类访问外部类属性,通过外部类名.this:---"+Out.this.name);
}
}
//2.外部类访问内部类,必须先有内部类对象
public void method() {
Inner inner = new Inner();
inner.function();
}
}
静态内部类访问规则
/**
******** 内部类的访问规则
* 1.内部类可以直接访问外部类的成员,包括私有
* 2.外部类访问内部类,必须建立内部类的对象
* 3.之所以内部类可以访问外部类,因为内部类中,持有外部类的引用,
* 格式: 外部类名.this
*
*****静态内部类访问规则
* 1.当内部类位于成员变量是时,可以被修饰符修饰,比如内部类私有
* 2.当内部类被static修饰时,访问外部类的成员必须也是静态的,因为静态内部类先于对象存在,所以必须访问静态的
* 3.访问静态内部类中的非静态成员,(获取静态内部类对象)
* Out.Inner in = new Out.Inner();
* 4.外部类访问静态内部类中的成员, 内部类名.静态成员属性
*
*总结(2019/07/31):对于静态内部类,就相当于创建了一个新的类,内部类与外部类
* 没有什么关系,这时候静态内部类就是一个普通的类,访问外部类的属性和方法,必须先创建
* 对象。
*
* @author mahao
* @date: 2019年2月14日 下午1:10:55
*/
/**
* 外部类 cesi
*/
class Out1{
static String name = "外部类属性";
String fiel = "普通属性";
//外部类访问静态内部类中的非静态属性
public void method() {
System.out.println("外部类访问静态内部类中的静态成员----"+Inner.name);
}
/**
*内部类
*/
static class Inner{
static String name = "内部类属性";
public void function() {
System.out.println("静态内部类只能访问外部静态成员变量------"+Out1.name);
System.out.println("静态内部类访问外部类普通成员变量-------"+new Out1().fiel);
}
}
}
public class InnerClassDemo2 {
public static void main(String[] args) {
//获取静态内部类中的对象
Out1.Inner in = new Out1.Inner();
in.function();
Out1 out = new Out1();
out.method();
}
}
内部类定义在方法中
/**
*内部类不在成员属性上,内部类定义在局部时,即定义在方法里面
*
* 1.不可以被成员修饰符修饰
* 2.内部类可以直接访问外部类中的成员变量,因为还持有外部类中的引用
* 但是访问方法里面的变量,只能被final修饰才可以
*/
/**
* 外部类
*/
class Out2{
private String name = "外部类属性";
public void method() {
final int x =3;
/**
*定义在方法上的内部类
*/
class Inner{
public void function() {
//1.內部類可以訪問外部類的屬性
System.out.println(name);
//2.内部类访问的局部变量必须被final修饰
System.out.println(x);
}
}
//方法里面创建内部类,并调用里面的方法
new Inner().function();
}
}
public class InnerClassDemo3 {
public static void main(String[] args) {
Out2 out = new Out2();
out.method();
}
}
匿名内部类
/**
* 匿名内部类
*
* 1.匿名内部类是对内部类的简写形式<br>
* 2.内部类必须有接口或者父类
*
* @author mahao
* @date: 2019年2月14日 下午7:39:22
*/
public class InnerClassDemo4 {
public static void main(String[] args) {
Out4 out = new Out4();
out.function2();
}
}
interface IN {
void method();
}
/** 外部类 */
class Out4 {
private String name="外部类属性";
/** 内部类 */
class Inner implements IN {
@Override
public void method() {
System.out.println("方法执行......");
System.out.println("内部类访问外部类属性---"+Out4.this.name);
}
}
// 外部类成员变量方法
void function() {
Inner in = new Inner();
in.method();
}
// 用匿名内部类简写为
void function2() {
// Inner in = new Inner();
// in.method();
final String methodName = "方法内的变量名";
/**
* 匿名内部类的格式
*/
new IN() {
@Override
public void method() {
System.out.println("方法执行2......");
System.out.println("访问外部类属性---"+Out4.this.name);
System.out.println("访问方法的局部变量---" + methodName);
}
}.method();
/*//反编译的结果,给匿名内部类生成了一个新的字节码文件,命名是Out4$1表示,Out4类中的第一个匿名内部类,
* 可以看到Out4$1中含有Out4的对象的引用this$0,获取外部类的属性都是通过这个引用。
* 对于方法中的局部变量,为什么要声明为final类型,是因为内部类中使用方法中的局部变量,是通过直接拷贝变量的值,
* 到内部类中去使用,如果局部变量的值,会发生改变,还有是保证声明周期。
*
class Out4$1 implements IN {
Out4$1(Out4 var1) {
this.this$0 = var1;
}
public void method() {
System.out.println("方法执行2......");
System.out.println("访问外部类属性---" + Out4.access$0(this.this$0));
System.out.println("访问方法的局部变量---方法内的变量名");
}
}
*/
}
}
代码中都有讲解,可以将代码粘贴出来,在IDE中运行一下,分析它的运行结果。java提供的内部类机制,本质是java的语法糖,和foreach,拆装箱所属一样,是为了简化操作,这些语法糖在编译期间将会被编译器‘解语法糖’,查看反编译之后的结果,更容易解答,匿名内部类粘贴出来了反编译后的结果。
源码练习地址