内部类就是将一个类的定义放在另一个类的定义内部。
内部类分类:
- 成员内部类
- 静态内部类
- 局部内部类(也称方法内部类或本地内部类)
- 匿名内部类
--------------------------------------------------------------------------------------
成员内部类
最普通的内部类,定义于另一个类内部
语法形式:
public class Outer{ //外部类
...
class Inner{//内部类
...
}
}
//Inner类就是Outer类的成员内部类
eg:
这样看起来,类BattleScore类像是类Hero的一个成员,Hero称为外部类,BattleScore类称为内部类。
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
内部类对象的创建
成员内部类是依附外部类而存在的
创建成员内部类对象的前提是创建一个外部类对象
外部类.内部类 对象名 = 外部类对象.new 内部类();
或
外部类.内部类 对象名 = new 外部类().new 内部类();
eg:
成员隐藏现象
在内部类调用与外部类同名的成员方法或者成员变量时,优先调用内部类自己的成员方法或变量
内部类中调用外部类方法或变量可以用this指针
外部类.this.成员变量
外部类.this.成员变量
外部类访问内部类成员
在外部类中无法直接访问成员内部类的成员
先创建一个成员内部类的对象,再通过对象来访问内部类成员。
内部类类名 对象名=new 内部类类名();
--------------------------------------------------------------------------------------
静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static
语法形式
public class Outer{ //外部类
...
static class Inner{//内部类
...
}
}
//Inner类就是静态内部类
eg:
静态内部类不需要依赖于外部类的对象,比如敌方水晶,当敌方水晶没有血的时候,己方所有英雄都取 得胜利,而不只是某一个具体的英雄取得胜利。
静态内部类不能使用外部类的非static成员变量或者方法。
静态内部类对象的创建
外部类.内部类 对象名 = new 外部类.内部类() eg:
--------------------------------------------------------------------------------------
局部内部类
局部内部类又叫方法内部类或本地(Local)内部类。
它是定义在一个方法或者一个代码块里面的类
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及 static修饰符的。
注意:如果局部内部类是定义在外部类的静态方法中的,则它无法访问外部类的非静态成员。
语法形式
public class Outer{
public void method(){
class Inner{//局部内部类
...
}
}
}
eg:
匿名内部类
匿名内部类是没有类名的局部内部类。
它的特点:
- 它是局部内部类-----定义在方法体内,或者代码块内
- 没有类名-----如何创建对象?
匿名内部类使用场景
一般用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的重写或是实现接口中规定的方法。
匿名内部类的主要使用场景就是多态
语法形式
因为匿名内部类没有类名,所以它不能像正常类一样创建对象,它只能在定义类的同时创建对象。
继承关系中的匿名类:
父类名 对象名 = new 父类名(){
//重写父类的某些方法 或 实现父类中的抽象方法
}
实现关系(接口)中的匿名类:
接口名 对象名 = new 接口名(){
//实现接口中的抽象方法
}
继承关系中的匿名类
eg:
无论是匿名子类还是正常子类,都需要实现父亲中的抽象方法
匿名类和正常类的区别就是没有类名,因此只能在创建类的同时创建对象。类名和构造方法均用父类的
接口中的匿名类
eg:
无论是匿名类还是正常实现类,都需要实现接口中的抽象方法
接口中的匿名类只能在创建类的时候创建对象,类名用接口名,使用无参构造函数(接口没有构造方法)
总结
- 成员内部类存在于类的内部,和属性、方法平级。成员内部类依赖于外部类对象存在,需要通过外部类 对象去创建内部类对象。
- 静态内部类不依赖于外部类的对象,可以直接new出来。
- 局部内部类存在于方法内或者代码块内,像局部变量一样,作用域很小,只能在所在的方法内(或代码 块内)使用。平时很少使用局部内部类。
- 匿名内部类是局部内部类的一种,它没有类名,因此不能随时随地创建对象,只能在创建类的同时创建对象。
lambda表达式
在Java中, lambda的本质是接口的实现类对象。
可以简化内部类的写法
eg:
lambda表达式语法
lambda表达式只能用于简化 函数式接口对应的匿名内部类
即只有一个方法的接口
由三部分构成:lambda形参列表、箭头、lambda方法体
语法格式:
(参数列表) -> { 方法体 }
箭头左侧是形参列表, 参数写在小括号里, 多个参数用逗号分隔
箭头右侧的是方法体, 用来写方法的逻辑.
方法体只有一行时可以省略大括号
(参数列表) -> 方法体
lambda语法的不同形式
1.无参数无返回值lambda
( )->{方法体}
如果没有参数, 小括号不能省略.
2.一个参数无返回值lambda
(参数类型 参数名)->{方法体;}
或
(参数名)->{方法体;}
或
参数名->{方法体;}
一个参数时可以直接写参数名,省略小括号
无论有多少个参数, 参数的数据类型都能省略, 应为编译器可以根据接口中的方法推断参数类型.
3.多个参数无返回值
(参数类型 参数名, 参数类型 参数名, 参数类型 参数名)->{方法体;}
或者
(参数名, 参数名, 参数名)->{方法体;}
4.多个参数有返回值lambda
(参数类型 参数名, 参数类型 参数名, 参数类型 参数名)->{方法体; return 结果;}
或者
(参数名, 参数名, 参数名)->{方法体; return 结果;}
如果方法体只有一行代码(即只有一个return语句时), 大括号和return能一起省略(不能只省略大括号).
省略的是大括号和return关键字,并不是省略return语句
方法引用
方法引用时特殊情况下lambda表达式的简化写法。
当外界已经有了与 函数式接口里抽象方法 匹配的方法时,可以使用方法引用
方法本质上是lambda表达式
lambda的本质是 函数式接口的匿名实现类对象!
方法引用的本质也是 函数式接口的匿名实现类对象!
eg:
方法引用使用格式
方法引用的使用格式一共有3种:
- 对象::非静态方法名
- 类::静态方法名
- 类::非静态方法名
Function BiFunction -----两个函数式接口
本文仅供自己学习所用