java内部类,Lambda,枚举类

目录

一.内部类

1.作用

2.语法

(一)非静态内部类

1.文件

2.访问外部类

3.同名变量

4.外部类访问内部

5.非静态内部类不能定义静态成员

(二)静态内部类

(三)使用内部类

(四)局部内部类

(五)匿名内部类

1.定义:

2.只使用一次,类定义就会消失

3.规则:

二.Lambda

1.作用

2.组成

 3.目标类型

4.保证目标类型

三.枚举类

1.区别

2.注意

3.实现接口的枚举类

4.包含抽象方法的枚举类


一.内部类

        定义在类内部的类被称为内部类,包含内部类的类被称为外部类。

1.作用

  1. 内部类的封装性更好,隐藏在外部类之内,不允许同一个包下的其他类访问该类
  2. 内部类可以直接访问外部类私有数据,外部类不能访问内部类的实现细节
  3. 匿名内部类用于创建只需使用一次的类

2.语法

        与外部类大致相同

        多了三个可用修饰符

        非静态内部类不能拥有静态成员

(一)非静态内部类

1.文件

        生成 外部类.class文件 和 外部类$内部类.class文件

2.访问外部类

        在非静态内部类的实例中,保存了一个它寄生的外部类的实例引用

3.同名变量

        访问顺序:局部变量-> 内部类变量this -> 外部类变量 外部类.this

4.外部类访问内部

        必须显式new一个非静态内部类实例

        外部类的静态成员不能直接访问非静态内部类,要创建一个外部类实例,再创建一个内部类实例。

5.非静态内部类不能定义静态成员

        因为非静态内部类是依赖于外部类实例存在的,而静态成员不依赖于任何实例,可以直接通过类名访问。如果在非静态内部类中定义静态成员,会导致编译错误。

(二)静态内部类

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

文件:相比(非)静,在$后多了数字,用于区分同名内部类

(五)匿名内部类

1.定义:

new 实现接口()|父类构造器(实参列表){...}

2.只使用一次,类定义就会消失

3.规则:

  1. 必须继承一个父类/实现一个接口,有且只有一个
  2. 匿名内部类不能为抽象类,会立即创建一个实例
  3. 不能定义构造器,可以有初始化块
  4. 被匿名内部类访问的局部变量,会自动加“final"
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);
    }
}

二.Lambda

1.作用

        简化匿名内部类,省略new Xxx

2.组成

  1. 形参列表,允许省略数据类型
  2. ()->{...}
  3. 代码块只有一条依据时可省,只有一条return语句时,可省return

 3.目标类型

        Lambda表达式类型必须是函数式接口,只包含一个抽象方法的接口。

表达式结果被当作对象。

4.保证目标类型

  1. 将Lambda赋给函数式接口类型的变量
  2. 将Lambda作为函数式接口类型的参数传给某个方法
  3. 使用函数式接口对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几乎一样

1.区别

  1. 可以实现一个/多个接口,但默认继承Enum类,而不是Object。因此不能继承其他父类 

  2. 枚举类默认final,不能派生子类

  3. 构造器只能是private修饰,可省

  4. 必须在第一行显式指出实例,自动“public static final”修饰

2.注意

        枚举类通常应该设计成不可变类,建议成员变量使用private final

        若使用final,应定义带参构造器,列出枚举时须传参

3.实现接口的枚举类

  1. 由枚举类型实现接口方法,每个枚举值调用此方法时,行为方式相同
  2. 由枚举值分别实现,则行为方式可以不同。#实际上就是枚举类发匿名子类。  

4.包含抽象方法的枚举类

        在枚举类中定义抽象方法,由其匿名内部子类实现。 

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();
}

你可能感兴趣的:(java学习,java)