目录
一.内部类
1.作用
2.语法
(一)非静态内部类
1.文件
2.访问外部类
3.同名变量
4.外部类访问内部
5.非静态内部类不能定义静态成员
(二)静态内部类
(三)使用内部类
(四)局部内部类
(五)匿名内部类
1.定义:
2.只使用一次,类定义就会消失
3.规则:
二.Lambda
1.作用
2.组成
3.目标类型
4.保证目标类型
三.枚举类
1.区别
2.注意
3.实现接口的枚举类
4.包含抽象方法的枚举类
定义在类内部的类被称为内部类,包含内部类的类被称为外部类。
与外部类大致相同
多了三个可用修饰符
非静态内部类不能拥有静态成员
生成 外部类.class文件 和 外部类$内部类.class文件
在非静态内部类的实例中,保存了一个它寄生的外部类的实例引用
访问顺序:局部变量-> 内部类变量this -> 外部类变量 外部类.this
必须显式new一个非静态内部类实例
外部类的静态成员不能直接访问非静态内部类,要创建一个外部类实例,再创建一个内部类实例。
因为非静态内部类是依赖于外部类实例存在的,而静态成员不依赖于任何实例,可以直接通过类名访问。如果在非静态内部类中定义静态成员,会导致编译错误。
1.静态内部类可以拥有静态成员、非静态成员
2.不能直接访问外部类实例成员
3.外部类可以通过静态内部类类名访问其类成员
1.在外部类中,可直接通过内部类类名 定义变量
public class Main {
public static void main(String[] args) {
Person p=new Person();
p.blink();
}
}
class Person{
private class Eye{
private int num=2;
public void blink(){
System.out.println("人在眨眼");
}
}
Eye e=new Eye();//显式new一个内部类实例
public void blink(){
e.blink();
}
}
2.在外部类之外使用非静态内部类,内部类不应使用private
OuterClass.InnerClass varName;//声明变量
OuterInstance.new InnerConstructor;//创建对象
创建内部类的子类时,非静态内部类的构造器必须使用外部类实例来调用
class Sub extends OuterClass.InnerClass{
public Sub(OuterClass out){
out.super();//非静态内部类是依赖于外部类实例存在
}
}
public class Main {
public static void main(String[] args) {
Person p=new Person();
p.blink();
Person.Eye e=p.new Eye();
e.blink();
}
}
class Person{
public class Eye{
private int num=2;
public void blink(){
System.out.println("人在眨眼");
}
}
Eye e=new Eye();//显式new一个内部类实例
public void blink(){
e.blink();
}
}
class Sub extends Person.Eye{
public Sub(Person p){
p.super();//非静态内部类依赖于外部类实例
}
}
3.在外部类以外使用静态内部类
OuterClass.InnerClass varName;//声明变量
new OuterClass.InnerConstructor;//创建对象
创建子类时,无需使用外部实例
public class Main {
public static void main(String[] args) {
Person p=new Person();
p.blink();
Person.Eye e=new Person.Eye();
Person.Eye.blink();
}
}
class Person{
public static class Eye{
private int num=2;
static public void blink(){
System.out.println("人在眨眼");
}
}
public void blink(){
Eye.blink();//通过内部类名直接访问
}
}
class Sub extends Person.Eye{
public Sub(){
super();
}
}
#优先考虑使用静态内部类
在方法中定义,不能使用访问控制符和static
文件:相比(非)静,在$后多了数字,用于区分同名内部类
new 实现接口()|父类构造器(实参列表){...}
public class Main {
public static void main(String[] args) {
int[] arr={3,4,5,2,1};
ProcessArr.process(arr, new Command() {
@Override
public void process(int[] arr) {
int sum=0;
for(int t:arr){
sum+=t;
}
System.out.println(sum);
}
});
}
}
interface Command{
void process(int[] arr);
}
class ProcessArr{
public static void process(int[] arr,Command cmd){
cmd.process(arr);
}
}
简化匿名内部类,省略new Xxx
Lambda表达式类型必须是函数式接口,只包含一个抽象方法的接口。
表达式结果被当作对象。
public class Main {
public static void main(String[] args) {
int[] arr={3,4,5,2,1};
ProcessArr.process(arr, (int[] temp)->{
int sum=0;
for(int t:temp){
sum+=t;
}
System.out.println(sum);
});
}
}
interface Command{
void process(int[] arr);
}
class ProcessArr{
public static void process(int[] arr,Command cmd){
cmd.process(arr);
}
}
enum关键字定义枚举类,与普通class几乎一样
可以实现一个/多个接口,但默认继承Enum类,而不是Object。因此不能继承其他父类
枚举类默认final,不能派生子类
构造器只能是private修饰,可省
必须在第一行显式指出实例,自动“public static final”修饰
枚举类通常应该设计成不可变类,建议成员变量使用private final
若使用final,应定义带参构造器,列出枚举时须传参
在枚举类中定义抽象方法,由其匿名内部子类实现。
public class Main {
public static void main(String[] args) {
System.out.println(Season.Spring.getName());//春天
Season.Spring.how();//多雨
}
}
enum Season implements climate{
Spring("春天"){
public void how(){
System.out.println("多雨");
}
},
Summer("夏天"){
public void how(){
System.out.println("闷热");
}
},
Autumn("秋天"){
public void how(){
System.out.println("凉爽");
}
},
Winter("冬天"){
public void how(){
System.out.println("寒冷");
}
};
private final String name;
private Season(String name){
this.name=name;
}
public String getName() {
return name;
}
}
interface climate{
void how();
}