Java内部类 lambda

嵌套类/内部类

一个类的内部又完整嵌套了另一个类的结构,被嵌套的类叫内部类 包含内部类的叫外部类,与外部类平级的叫外部其他类

内部类的特性: 可以直接访问外部类私有(private)属性
这里用的是非静态嵌套类/成员内部类/内部类举例

class Outer{//外部类
    private int age = 0; //外部类私有属性
    class InnerClass{//内部类
    
    }
}
class OuterOther{//外部其他类
    
}
嵌套类/内部类的称呼

大致为四种,不同书籍课本有不同的描述

  1. 非静态嵌套类简称 内部类 /成员内部类
  2. 静态嵌套类 / 静态内部类 (不规范)
  3. 匿名嵌套类 / 匿名内部类
  4. 局部嵌套类 / 局部内部类

其中日常 用的比较多的是 非静态嵌套类/匿名嵌套类

非静态嵌套类/成员内部类/内部类

放置在外部类的成员位置上,非静态的内部类
下图中描述了内部类InnerClass与外部类DaysOfTheWeek的关系
在这里插入图片描述

  1. 内部类可以访问外部类的私有成员

  2. 上图中 外部类方法 中创建的内部类对象并不是 外部类的属性 而是 外部类方法的局部变量

  3. 只有内部类才能被四种修饰词所修饰(private/默认/protected/public)普通类只有 默认(包内可见)/ public(公有可见)

  4. 将内部类 私有化 只有外部类的方法才能够创建内部类的对象 (此时只有外部类能通过 方法去实例化 私有内部类 外部其他类无法访问 私有内部类)

  5. 该点结合下图食用 内部类可以隐藏外部类的同名字段,当内部类声明的属性 与外部类的某个属性名称 相同,此时在内部类中隐藏了外部类的属性,只能访问到内部类的那一个属性(简单来说就是 内部类某个属性名称 与 外部类的某个属性的名称 相同,那么在内部类里面就只能访问到自己的了,外部类的那一个被隐藏掉了) 若需要访问则需要通过 类名.this.属性名 (当前是非静态内部类,所以需要外部类的一个载体去访问)
    隐藏外部类属性

  6. 想要使用非静态嵌套类/内部类,就必须有一个外部类作为载体。首先要新建一个外部类对象,再通过外部类对象去实例化一个内部类对象 (前提是符合访问修饰符,内部类不能是私有化的)在这里插入图片描述

  7. 非静态嵌套类中不使用static修饰的属性或方法。
    这破玩意有好多种解释的方法,反正我是被迷惑了
    但是个人认为无论如何,在非静态内部类设置static修饰的方法是多余的
    因为想要设置static肯定是想让某个属性/方法在 任何外部类的任何内部类中共享,想要完成这一点可以直接在外部类中添加

  8. 静态内部类与非静态内部类差别就是,非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外部类的对象,但是静态内部类却没有这个引用。

静态嵌套类/静态内部类

静态嵌套类的语法格式 是在 非静态嵌套类的基础上在类名前加static修饰符,但是使用方法有较大区别。(静态属性不用实例化对象就能访问,静态方法不能使用实例属性)

  1. 静态嵌套类只能方位外部类的静态属性及静态方法,不允许访问外部类的非静态字段
    • 因为静态嵌套类不需要基于任何外部类的对象,可以自己独立实例化。
      此时若可以访问外部类的非静态字段(由于非静态字段是属于某个对象),那么到底访问的是哪个对象呢?所以根本不存在,也就不能访问
public class InnerClassTest {
    int a = 1;
    static int b = 2;
    private int c = 3;
    private static int d = 4;
	//静态嵌套类类
    static class Inner2{
        void test(){
            System.out.println(a);  //外部类属性  错误    
            System.out.println(b);  //外部类静态属性
            System.out.println(c);  //外部类私有类属性  错误
            System.out.println(d);  //外部类静态私有属性
        }
    }
  1. 若要在 外部其他类 中创建 静态嵌套类 的对象,此时不需要 实例化 外部类 对象,直接通过类名实例化
    在这里插入图片描述

匿名嵌套类/匿名内部类

匿名嵌套类 是一个匿名的类,并且是在类里面嵌套一个类并实例化的过程
下面是示例代码

public class test {
    public static void main(String[] args) {
    
        Toy car = new Toy() {
            @Override
            public void play() {
                System.out.println("play car toy");
            }
        };//自动继承Toy类,但是这个类是匿名的,没有类名,只知道继承了Toy
        
        car.play();//此时调用的是重写后的方法
    }
}

class Toy{
    public void play(){
        System.out.println("play toy");
    }
}
实际使用场景

匿名嵌套类 多用于调用方法时的传参 参数是一个接口类型 临时创建一个匿名嵌套类并实例化 传参

方法传参时传接口类型 在之前需要写类实现接口 然后实例化一个对象进行传参 学了匿名内部类之后,直接在传参时写一个类,实例化对象(实现接口)

直接new一个类,new超类的类名(构造参数){方法}

public class Array_ {
		//注意这个mysort接口很重要,在后面实现的匿名嵌套类使用
	interface mySort{
	    int compare(Object o1,Object o2);
	}
    public static void main(String[] args) {
        Integer[] integers = {1,2,3,4,5,6,7,8,9,0,11,5,8};

        //定制排序 (使用匿名内部类,重写父类的排序逻辑)
        //定制排序重载, 预设了一个通道为下面方法的第二个参数(接口)
        //第二个参数能够重写compare方法,返回值大于0小于0会影响到排序的方式
        //接口编程 动态绑定 匿名内部类

        //自己写的一段模拟系统的compare方法
        myBubbleSort01(integers, new mySort() {
            @Override
            public int compare(Object o1, Object o2) {
                int i1 = (Integer)o1;
                int i2 = (Integer)o2;
                return i1 - i2;
            }
        });//在这里 创建并实例了匿名内部类,该类实现mySort接口,并实现里面的方法
        
        System.out.println(Arrays.toString(integers));

    }

		//这里是排序方法,传入需要排序的数组,和排序接口的实现子类的对象
    public static void myBubbleSort01(Integer[] arr,mySort mysort){
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i-1; j++) {
                if(mysort.compare(arr[j],arr[j+1])>0)
                //重点在这上方,调用接口的compare方法得到对比返回值
                {
                    arr[j] = arr[j] ^ arr[j+1];
                    arr[j+1] = arr[j]^ arr[j+1];
                    arr[j] = arr[j] ^ arr[j+1];
                }
            }
        }
    }

}

更多关于匿名内部类的细节可以参考匿名内部类的作用

Lambda表达式

简写匿名内部类的方法,有一个大前提,该类是实现的是函数式接口,即该接口中只能有一个方法 注意,只能是接口并且只有一个方法

区分lambda表达式与语句

lambda表达式 结果回自动return返回

lambda语句 至多三行,花括号包住
若要有返回值必须写return

lambda表达式若要指定数据类型必须全部指定

public class Array_ {
	interface mySort{
	    int compare(Object o1,Object o2);
	}
    public static void main(String[] args) {
        Integer[] integers = {1,2,3,4,5,6,7,8,9,0,11,5,8};
        myBubbleSort01(integers,(o1, o2) -> (int)o1-(int)o2);//表达式
        //下面是语句!需要手动返回设置返回值!
        myBubbleSort01(integers, (o1, o2) -> {
            int i1 = (Integer)o1;
            int i2 = (Integer)o2;
            return i1 - i2;
        });
    }

		//这里是排序方法,传入需要排序的数组,和排序接口的实现子类的对象
    public static void myBubbleSort01(Integer[] arr,mySort mysort){
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i-1; j++) {
                if(mysort.compare(arr[j],arr[j+1])>0)
                //重点在这上方,调用接口的compare方法得到对比返回值
                {
                    arr[j] = arr[j] ^ arr[j+1];
                    arr[j+1] = arr[j]^ arr[j+1];
                    arr[j] = arr[j] ^ arr[j+1];
                }
            }
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值