day12_java内部类

内部类

什么是内部类

内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权限)。

内部类的好处

  • 内部类方法可以访问该类定义所在的作用域的数据,包括私有的数据

  • 内部类可以对同一个包中的其他类隐藏起来,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以

  • 可以实现多重继承

  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷

  • 每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。Java只能继承一个类,它的多重继承在我们没有学习内部类之前是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类。

内部类分类

  • 成员内部类:
    实例内部类、
    静态内部类(类内部类)
  • 局部内部类
  • 匿名内部类

1.实例内部类

语法:

Class Outer{
Class Inner{
}
}

实例内部类访问修饰符

实例内部类注意

  • 实例内部类内部不允许定义任何静态内容
  • 外部类静态方法中不能访问实例内部类数据
  • 如果外部类成员变量、内部类成员变量、内部类方 法中局部变量同名

实例内部类的字节码文件名: 外部类名$内部类名.class


class Cat{

    public Cat() {
        super();
        // TODO Auto-generated constructor stub
    }

    private double Weight;
    public Cat(double Weight){
        this.Weight = Weight;
    }

    //实例内部类
    class CatBody{
        private String color;
        public CatBody(String color){
            this.color = color;
        }
        public void show(){
            //内部类访问外部类 :直接访问,因为内部类对象中都隐藏着一个外部类对象   外部类名.this
            System.out.println("颜色:"+color+Cat.this.Weight);
        }
    }

    public void dispaly(){
        System.out.println("ggg"+this.Weight);
        Cat cat = new Cat(22.2);
        System.out.println(cat.Weight);
        //外部类访问内部类的成员  用内部类的对象 来访问
        CatBody body = new CatBody("白色");
        body.show();

    }

}

public class TestInner{
    public static void main(String [] args){
        Cat cat = new Cat(44.4);
        cat.dispaly();
        //创建内部类的对象
        Cat.CatBody body = cat.new CatBody("黑色");
        body.show();

        //                  匿名对象    只能使用一次
        Cat.CatBody body1 = new Cat(55.5).new CatBody("蓝色");
        body1.show();
    }
}


2.静态内部类

语法

class Outer{
static Class Inner{
}
}

访问修饰符

静态内部类注意

  1. 内部类中不可以定义静态成员,但是可以定义Static final成员
  2. 外部类静态方法中不能直接访问实例内部类数据,但是可以访问Static final
  3. 外部类成元变量、内部类成员变量、内部局部变量重名

字节码文件名:外部类名$内部类名.class


class School{
    //静态内部类,属于外部类所有
    static class WaterFoundation{
        int water = 65;
        static int water1 = 100;

        public void show(){
            System.out.println(water);
        }

        public static void show1(){
            System.out.println(water1);
        }
    }



    public void manager(){
        //访问水量
        //访问静态内部类中的实例成员,用静态内部类对象访问
        WaterFoundation w = new WaterFoundation();
        w.show();
        //访问静态内部类中的静态成员,用静态内部类名访问
        WaterFoundation.show1();
    }
}

public class TestStaticInner {

    public static void main(String[] args) {
        School school = new School();
        school.manager();
        //属于外部类,所以访问的时候不需要创建对象
        School.WaterFoundation sw = new School.WaterFoundation();
        sw.show();
        sw.show1();//类名.静态成员

    }

}

3.局部内部类

语法

方法中定义类,局部
class Outer{
public void function(){ class Inner{
}
}
}

局部内部类注意

  • 局部内部类不能声明静态成员
  • 局部内部类处于静态方法中只能访问外部类静态成 员
  • 局部内部类处于实例方法中可访问外部类静态成员 和实例成员
  • 局部类对局部变量的访问

字节码文件名 :外部类名$内部类名.class



public class TestLocalInner {
    static int sn = 33;
    int num = 44;
    public void f(){
        //8.0之前要加上final才可以访问
        //8.0之后可以不加final,但是值不能更改,改了就不能访问
        int x = 56;//局部变量
        class Inner{
            public void show(){
                //实例方法    都可以访问
                System.out.println(sn + num +x);
            }
        }
    }

    public static void main(String[] args) {
        //局部内部类
        class Base{
            static final int n = 55;
            int x = 55;
            public void show(){
                System.out.println(sn);
                //静态方法内不能直接访问非静态成员,可以通过对象访问
                //System.out.println(num);
            }
        }
        class Sub extends Base{
            int y = 66;
        }
        Sub sub = new Sub();
        System.out.println(sub.x+","+sub.y);
    }
}

4.匿名内部类(重点)

前提

必须继承一个父类或者实现一个接口

语法

new 父类(参数列表)  或者实现接口(){
    //匿名内部类的类体部分
}

字节码文件名 :外部类名 $N.class

好处

注意:

  • 必须实现一个类或一个接口。
  • 不能定义静态数据
  • 不能定义构造器
  • 不能定义构造器
  • 不能是抽象的
  • 传参问题
  • 同名问题
abstract class Base{
    String s;
    public void f(){}

    public abstract void af();
}

class NoNameClass{
    //父类类型  引用    =   匿名子类对象
    //可以是静态的,不能是抽象的
    Base base1 = new Base(){
        public void f(){
            System.out.println("f");
        }
        //子类独特的功能被屏蔽,不能用
        public void func(){}
        @Override
        public void af() {
            // TODO Auto-generated method stub

        }


    };


    public void function(){
    new Base(){
        public void f(){
            System.out.println("f");
        }
        //子类独特的功能被屏蔽,不能用
        public void func(){}
        @Override
        public void af() {

        }       
    }.func();
    }

}



public class TestNoNameInner {

    public static void main(String[] args) {

        NoNameClass n = new NoNameClass();
        n.base1.f();    
        //用的接口名称,但是创建的是子类的对象
        new Base(){
            public void f(){
                System.out.println("f");
            }

            @Override
            public void af() {
                // TODO Auto-generated method stub

            }

        }.f();

    }

}

Lambda

函数式接口

只含有一个抽象方法的接口称为函数式接口

Lambda语法

(参数)—>(语句;)

Lambda表达式:

作用:替换匿名内部类的语法。
注意:只能能应用于 函数式接口。

方法引用

Lambda中只有一行代码,代码中只调用了一个方法


//函数式接口
@FunctionalInterface
interface la{
    //只含有一个抽象方法的接口称为函数式接口
//  int func();
//  void func();

//  void func(int n );
    int func (int n);
/*  default void df(){}
    static void sf(){}*/


}

//方法一
/*class LaImpl implements la{

    @Override
    public void func() {
        // TODO Auto-generated method stub

    }

}*/

class LaDemo{

    //方法二  匿名内部类的方式
/*  la a = new la(){
        public void func(){
            System.out.println("func");
        }
    };*/
    //方法三  Lambda无参数无返回值
//  la a1 = ()  ->  {System.out.println("func");};
//  la a2 = ()  ->  System.out.println("func");

    //无参数有返回值
    /*la a1 = () -> {return 11;};
    la a2 = () -> 11;*/

    //形参列表
//  la a1 = (m) -> {System.out.println(m);};

    //带参数带返回值
    //la a1 = (n)-> {return n;};
    //la a1 =n-> n;
}

public class TestLambda1 {

    public static void main(String[] args) {
        LaDemo demo = new LaDemo ();
//      demo.a.func();

    }

}

匿名内部类和 Lambda的区别

  1. Lambda只针对于函数式接口,匿名内部类 对接口,普通类,抽象类都可以

Lamdba表达式调用Arrays中的方法


//Lambda表达式调用Arrays中的方法
import java.util.Arrays;
import java.util.function.IntUnaryOperator;

/**
 * 
 * @author daidai
 *
 */
public class Ex2 {

    public static void main(String[] args) {
        int [] arr ={1,2,3,4,5};
        System.out.println(Arrays.toString(arr));
        //用一元运算的结果对数组元素替换
        //数组下标的替换
        Arrays.parallelSetAll(arr, new IntUnaryOperator(){
            public int applyAsInt(int operand){
                return operand;//下标
            }
        });


        Arrays.setAll(arr, o->{return o; });


        //用二元运算结果
        Arrays.parallelPrefix(arr, new IntBinaryOperator(){
            @Override
            public int applyAsInt(int left ,int right){
            //right是当前元素,left是前一个元素
            //当前元素是第一个时,前一个元素是1
            return left * right;
            }
        });

        String s = Arrays.toString(arr);
        System.out.println(s);


        //遍历数组
        //  Stream流的用法
        Arrays.stream(arr).forEach(e -> {System.out.println(e);});
        //方法引用
        Arrays.stream(arr).forEach(System.out :: println);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_24135817/article/details/80576733