内部类:
一般在源代码出现,自己写的比较少
分类:
在类的成员位置:成员内部类
在类的局部位置:局部内部类(在方法中编写)
静态内部类
public class M0{
private int a = 10;
class M1{-------------在类M0的成员位置
int num = 20;
public void m(){
sout("我是成员内部类")
sout(a)}}}-------------可以访问类M0的私有成员
调用方式:
M0.M1 s = new M0() . new M1();
s.m();---------"我是成员内部类"、10
sout(s.num)------------------20
内部类可以被私有化:
当出现私有化,外部访问不到时
----解决方式:
可在类中创建一个可以被外类访问的public方法,在方法内部去访问私有
public class M0{
private class M1{----------被私有化的内部类
public void m(){sout("xxx")}}
public void method(){
M1 s = new M1();---无需M0.M1 s = new M0() . new M1();因为已经在M0这个类中,直接调用即可
s.m();}}}
public class Test{ psvm { M0 s = new M0() ; s. method(); }}
静态内部类:
class Outer{
static class Inner{
public void show(){ sout("xxx") }
public static void method(){ sout("oooo") }}}------------静态内部类中的静态方法
psvm{ Outer.Inner s = new Outer.Inner();-------静态内部类的创建方式
s . show();
Outer . Inner . method() ; }---------静态内部类中静态方法的访问方式
局部内部类:
很少使用,目的是为了匿名内部类打基础。
创建在方法中,只能在方法内部创建局部内部类对象访问,最后创建Outer,去调用方法(局部内部类在里面)
class Outer{
int a = 10;
public void method(){
int b =20;
class Inner{
public void show(){
sout("xxxx"+a+b)}}
Inner s = new Inner();
s.sout();}
}
psvm{
Outer s = new Outer();
s.method();}
匿名内部类:(用的比较多)
含义:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部)
前提:需要存在一个接口或类
格式:
new 类名/接口名(){ 重写方法 };
作用:匿名内部类就是将 ( 继承 / 实现 )、(方法重写)、(创建对象)统一。(无需再实现接口、重写接口方法、创建实现类对象。或无需继承、重写父类方法、创建子类对象)
注意:在写完匿名内部类,一定要调用接口中的方法,否则运行没有内容
psvm{ InterImpl s = new InterImpl();(和new Inter()类似)
s.show();
new Inter(){--------------实现了Inter接口的,一个实现类对象
@Override
public void show(){sout("xxx")--------------重写方法
}.show();-----------实现类对象.show();调用方法
}}
Interface Inter{
void show();}
class InterImpl implements Inter{
public void show(){sout("xxx")}}
若接口存在多种方法(可用多态调用方法)
Interface Inter{
void show1();
void show2();}
Inter s = new Inter(){ ---------接口父类 指向 实现类对象 形成多态(有接口有重写)
@Override
public void show1(){sout("xxx")}
@Override
public void show2(){sout("2x2x2x")}
} 因无法在此处调用两个方法,为了简明,用多态调用
s.show1();
s.show2();
匿名内部类的应用场景:
当方法参数为接口时,可以传入实现类
即 接口 s = 实现类对象 (父类指向子类 → 多态)
s.swim();
编译看父类,运行看子类,也就是子类的重写
Lambda:
理解上来说:是对匿名内部类的优化
格式:
(形参) -> { 代码块 }
使用前提:
1.有一个接口(操作一个接口,即方法参数为接口),必须使用接口
2.接口只能有一个抽象方法(其他不做限制,即可以有其他方法,但抽象方法只能有一个)
匿名内部类 面向对象 更多关注怎么做 谁来(哪个对象)来做 | Lambda 更多关注做什么 函数式编程 不用关注对象 |
函数式编程思想:
在数学中,函数就是有输入量、输出量的一套计算方案。
函数:一个数会随另一个数的变化而变化
use( (String s)-> {sout("ss"+m)})-------s为参数,右边为重写方法
public static void use(S s){s.no("it")}------------对参数S接口进行操作
interface S{ void no (Sting s);}-------只有一个抽象方法
无参/有参 有返回值 (和上面一样,只是代码块多了一个return)
Lambda省略模式:
1.参数类型可以省略,若参数为多个,参数的类型不能只省略一个
2.当参数只有一个可以省略括号(没有参数括号不能省略)
3.当代码块只有一条语句,大括号、return、;分号,全部都可以省略,但要省全省,不能只省略一部分
Lambda表达式和匿名内部类的区别:
所需类型不同:
匿名内部类:可以式接口,也可是抽象类,也可以是具体类
lambda:只能是接口
使用限制不同:
若接口中只有一个抽象类,可用匿名内部类,也可用lambda
但多于一个抽象方法,只能用匿名内部类
实现原理不同:
匿名内部类:编译之后产生一个单独的.class字节码文件
lambda:编译后,没有单独产生.class文件,对应的字节码文件会在运行时动态生成(右键idea的java文件→show in Exploer → 会显示文件位置 → 返回到out → 运行检查即可)