内部类
成员内部类
外部类对内部类的变量做隐藏,成员允许访问权限修饰符
外部类无法直接访问内部类,需要创建内部类指向这个对象引用才能访问
成员内部类的创建方式: (必须存在外部内存对象)
这有点像板栗🌰
内部类可以访问外部所有权限成员,就像果肉可以吸收果皮的营养物
外部类需要创建内部类才可以访问,需要将果皮拨开果壳先拨开才能取出里面果肉
静态内部类
不需要依赖外部类,和类的静态成员属性有点类似,并且它不能使用外部类的非Static变量或方法
注意:内部类类名冲突,需要访问外部类+内部
// 常规
new Outter().new Inner()
Outter.Inner 内部对象名 = outter.method()
// static
Outer.Inner inner = new Outer().Inner();
inner.method();
// private(只能外部类中访问)
new Inter().method;
局部内部类
就像方法里面的局部变量,不允许任何权限修饰符
作用域:方法中
由于局限度高,使用率少
匿名内部类【重点】
匿名内部类为局部内部类的一种,因此局部内部类的限制同样生效。匿名内部类必须来完成继承类或实现接口的使命。
Lambda无法对抽象类操作,不强调增加额外方法,强调实现或重写,继承类或实现接口,二选一,二者不可兼得。
访问权限由所在成员方法块决定,无法自行定义。
由于构造方法是参照类名,匿名内部类是唯一没有构造方法的类
用于编写事件监听代码
注意:局部内部类 和 匿名内部类
1.7只能访问局部Final变量
1.8参数不被二次修改即可
目的:防止Thread线程在执行Run方法时改变变量a的值,会造成数据不一致性。成员实例变量都存储在堆中,堆是线程共享的。而局部变量则保存在栈上。如果Lambda可以直接访问局部变量,而且Lambda是在一个线程中使用的,则使用Lambda的线程,可能会在分配该变量的线程将这个变量收回之后,去访问该变量。Java为避免这个问题,在访问自由局部变量时,实际上是在访问它的副本,而不是访问原始变量,出现脏读问题。为了保证局部变量和lambda中复制品的数据一致性
- Java编译器限定必须将传参为Final修饰变量
- 不使用Final,对常量保证值引用不被改变,对引用类型数据保存地址值不被改变
对于集合切换内容,list2 = list1 会报错是因为 = 相当于把list的内存地址给了 list2 也就是改变了list2的值,所以编译会报错。 如果想实现这个功能可以使用list2.addAll(list1)
[ 方式一 ] 面向对象思想
// New 接口或父类(){ 重写方法/实现方法 ; } ;
OverriedClass OverriedObj = new OverriedClass() {
@Override
public void method() {
System.out.println("我是匿名内部类,我能实现接口,能重写类,能重写抽象类");
}
};
Lambda表达式快捷键 :对匿名内部类 Alt+回车 自动转为Lambda格式
[ 方式二 ] 函数式编程思想(函数有输入输出即方法,常用于方法参数的实现)
此方式仅针对接口的实现,不能继承重写类,且要求接口中抽象方法仅有一个,代码块更加强调重写内容,若有返回值则必须return
// New 接口或父类(){ 重写方法/实现方法 ; } ; 或 方法(匿名对象)
Method((parameter1,paramenter2)->{
System.out.println(parameter1+paramenter2);
System.out.println("我是Lambda表达式,我不能对抽象类进行实现,否则会报错");
},parameter3);
// 省略模式:省略数据类型,有且单个形参可以省略(),方法体仅一条且不能是return可以省略{}
Method(()->System.out.println("没有任何参数的的Lambda表达式进行了省略模式策略");
);
Exception:Target type of a lambda conversion must be an interface
当Lambda对抽象类进行实现将会抛出错误
如果一定要对抽象类操作,需要使用继承类重写方法,然后Lambda对继承实现类重写
Lambda与匿名内部类区别
使用范围不同 | 实现原理不同 | |
---|---|---|
匿名内部类 | 可以对具体类重写和接口实现,抽象类实现 | 匿名内部类:编译产生一个单独的.class文件 |
Lambda | 内部类简化版,仅仅只能对单个方法的接口进行实现 | Lambda表达式:编译后不会产生.class文件,对应的字节码会在运行时动态生成,运行在内存,不会保存到磁盘,除非使用JVM参数 |
对于Lambda表达式不生产class文件请点击阅读此处文章
方法引用::
如:Runnable 、 Comparator
语法:</classname or instancename> :: < methodname >
具体阅读
或者点击此处