day11

33. 内部类

分类特殊点
成员内部类定义在成员位置,分别具有成员以及类的特点,成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象,代码实现见33.1
私有内部类其他类无法使用!!! ,代码实现见33.2
静态内部类只有静态内部类中能直接定义并使用静态内容,且静态内部类是不持有指向外部类对象的引用的,即只创建一个对象 ,代码实现见33.3
局部内部类定义在局部,不能被成员修饰符修饰,只能被final修饰,代码实现见33.4
匿名内部类属于特殊的局部内部类,但声明以及创建对应实例的方式比较特殊,代码实现见33.5
33.1 成员内部类
public class Outer {

    private int a = 6;
    private static int i = 6;

    class inner {
        /*
        * 当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
          外部类.this.成员变量
          外部类.this.成员方法
* */

        private int a = 7;
        public void Use(){

            //static int j = 10; 会报错,除了只有静态内部类允许直接定义静态内容

            System.out.println("内部类方法");
            System.out.println(a); //默认使用成员内部类自己的成员
            System.out.println(this.a); //成员内部类
            System.out.println(Outer.this.a); //外部类的private成员
            System.out.println(i);
            System.out.println("同名默认调用成员内部类中的");
            // Use();

            // Outer.this.Use();

            System.out.println(i);

        }
    }

    public void Use(){
        System.out.println("外部类成员方法");
        System.out.println(a);
        /*成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。
        在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问*/
        System.out.println(new inner().a);
        System.out.println(i);
    }

}
 class TestOuter {
    public static void main(String[] args) {
        //成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象
        //即使用内部类要创建两个对象!!!
        Outer.inner inner = new Outer().new inner();
        inner.Use();
        new Outer().Use();
    }
}
33.2 私有内部类
public class Outer_2 {

    private int a = 3;
    static int x = 3;

    //私有内部类
    private class Inner{
        private int b = 4;
    }

    public Inner getInner(){
        return new Inner();
    }

}

class Test{
    public static void main(String[] args) {
        //new Outer_2().Inner();  报错!!!私有内部类在其他类中无法使用
        Outer_2 oo = new Outer_2();
        //Outer_2.Inner inner = oo.getInner();  报错!!!可以看到即使提供了获取对象方法也无法使用!!!

    }
}
33.3 静态内部类
public class Outer_3 {
    static int a = 3;
    int b = 4;

    static class Inner{
        static int c = 6;
        int d = 8;

        public void a(){
            System.out.println(c); //内部类静态成员
            System.out.println(d); //内部类成员
            System.out.println(a); //外部类静态成员
            System.out.println(new Outer_3().b); //外部类成员
        }

        public static void b(){
            System.out.println(c); //内部类静态成员
            System.out.println(new Inner().d); //内部类成员
            System.out.println(a); //外部类静态成员
            System.out.println(new Outer_3().b); //外部类成员
        }
    }
}

class TestA{
    public static void main(String[] args) {
        /*
        * 静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的
        */
        Outer_3.Inner inner = new Outer_3.Inner(); //注意new的方式是 外部类名.内部类()
        inner.a(); //内部类成员方法
        Outer_3.Inner.b(); //内部类静态方法
    }
}
33.4 局部内部类
public class Outer_4 {

    int i = 6;
    static int x = 7;

    public void use(){
        int a = 6;

        //只能在当前方法内使用,在外部类的其他方法以及其他类中都无法使用
        class Inner {
            int p = 10;
            int z = 11;

            //static int v = 10; 报错,static只修饰成员
            static final int y = 88888; //只能final和static一起使用

            public void InnerUse(){
                System.out.println(i);
                System.out.println(x);

                System.out.println(y);
                System.out.println(z);

                System.out.println(a);
                //a++; 报错 方法中的局部变量在局部内部类中使用后就只能为常量 , 包括方法形参!!!
                //JDK1.7及之前,需要手动final修饰
                //JDK1.8及之后,该变量默认被final修饰

            }

        }

    }
}
33.5 匿名内部类

匿名对象的三种使用方式

public class AnonymousInnerClass {
    /*
    *  匿名内部类,我的理解是只在当前作用域用到的次数不多的 接口实现类或者子类 ,不需要它的名字,只要实现对应的功能
    *  比如我现在就想看一场表演,不管是谁表演
    *
    *  匿名内部类 可以将 定义实现类并重写方法的过程 和 创建实现类对象的过程 合二为一
    */
    public static void main(String[] args) {
        //匿名对象第一种使用方式
        new Perform(){

            @Override
            public void acting() {
                System.out.println("唱歌表演");
            }
        }.acting();

        //匿名对象第二种使用方式,用对应的接口或抽象父类声明变量并接收匿名对象的引用,后续可多次使用 ( 多态 )
        Perform p = new Perform(){

            @Override
            public void acting() {
                System.out.println("跳舞表演");
            }

        };
        p.acting();

        //匿名对象作为方法实参传入
        performing(new Perform() {
            @Override
            public void acting() {
                System.out.println("摇摆");
            }
        });

    }

    public static void performing(Perform p){
        p.acting();
    }

}


interface Perform{
    void acting();
}

34. Lambda表达式

34.1 定义及使用

Lambda 表达式是匿名内部类的简化写法。

  • JDK1.8及以后

  • 作用 : 简化满足条件的匿名内部类对象

  • 前提 : 实现的是函数式接口 : 接口中只有一个必须被重写的抽象方法,可存在默认方法以及静态方法等存在方法体的方法

  • 检测函数式接口 : @FunctionalInterface 注解
    Lambda 属于函数式编程思想。
    只关注匿名内部类中最核心的这些内容(方法参数,方法体,返回值)

  • 将方法实现(某个行为)当做参数传递

    面向对象思想:怎么做。
    函数式编程思想:做什么。

  • -> Lambda符,也叫上下文推导符

34.2 代码实现
public class Lambda {
    public static void main(String[] args) {
        //匿名内部类实现方式
       /* Study s = new Study(){
            @Override
            public void Test() {
                System.out.println("学生学习");      // void Test();
            }
        };*/

        //注意,都省略关键的一点,就是new 函数式接口的过程
        //Lambda标准写法 ( ) -> { }
        //Study s = () -> { System.out.println("学生学习");};     // void Test();

        //Lambda写法2 : 方法体(无返回值)可省略{ }
        //Study s = () ->  System.out.println("学生学习");        // void Test();

        //Lambda写法3 : 参数列表只有一个时,( )可省略,参数类型也可省略
        //Study s = a ->  System.out.println("学生学习"+a);       // void Test(int a);

        //Lambda写法4 : 参数列表有多个时,仅参数类型省略                // void Test(int a,int b);
        //Study s = (x,y) ->  System.out.println("学生学习"+x+y);   //结果不同12
        //Study s = (x,y) ->  System.out.println("学生学习"+(x+y)); //       3
        //s.Test(1,2);

        //Lambda写法5 : 当方法体只有一句且为return带出返回值语句时,{ } 和 return可一起省略
        //Study s = a -> a>=18 ;                                // boolean Test(int a)
        //System.out.println(s.Test(16));


        //Lambda用法6 : 作为实参传入方法
        studying( () -> System.out.println("正在学习") );
    }

    public static void studying(Study s){
        s.Test();
    }

}

@FunctionalInterface
interface Study{
    void Test();
    //void Test(int a);
    //void Test(int a,int b);
    //boolean Test(int a);
}
34.3 方法引用

基本概念及使用:

1、写一个函数式接口时,方法的实现(lambda体),已经被某个其他的对象实现了,就不需要在Lambda体中,再次调用这个实现,而可以直接使用那个已经定义好的方法。
2、格式:
函数式接口 名称 = 对象名 :: 方法名称;
函数式接口 名称 = 类名 :: 静态方法名;
3、作用:
把已经实现的方法,作为一个数据,作为实现类对象,赋值给某个函数式接口的引用
可以把这个引用当做方法的返回值,也可以作为方法的实际参数进行传递
4、本质:
可以把任意一个方法,作为函数式接口的一个实现类对象

这里分为静态方法引用,和对象的实例方法引用

代码实现

public class TestLambda {
    public static void main(String[] args) {

        //1.普通Lambda实现函数式接口
        A a = s -> System.out.println(s);
        a.show("nuc");


        //2.使用方法引用实现函数式接口
            //调用实例方法
        //          对象名 :: 方法名
        A a1 = System.out :: println;
        a1.show("edu");
        a1.show("ygh");
        A a2 = new InterImpl() :: fun;
        a2.show("26000");

           //调用静态方法
        //            类名 :: 静态方法名 
        A a3 = InterImpl2 :: fun;
        a3.show("15");


    }
}

abstract interface A{
    void show(String s);
}
class InterImpl{
    public void fun(String s){
        System.out.println(Integer.parseInt(s) + 5);
    }
}

class InterImpl2{
    public static void fun(String s){
        System.out.println(Integer.parseInt(s) + 10);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值