java 内部类

使用java内部类的好处

  • 完善多重继承
    java只允许子类拥有一个超类,不可以拥有多个超类,如果想要扩展更多的功能,只能选择实现接口。
  • java实现事件驱动系统
    在java的GUI中使用了大量的内部类,用来响应各种事件处理,但是因为博主不使用GUI,就没有进行深入了解。
  • 闭包
    内部类是面向对象的闭包,它可以创建内部类自己的作用域,可以访问自身的数据域,同时内部类中拥有一个指针指向外部类,因此也可以访问创建它的外部类对象的数据域。如果父类和实现的接口拥有同名的函数,又不想失去父类函数,那就可以采用内部类去调用父类中对应的函数。

内部类的一些要点

  • 内部类对象可以访问自身的数据域,还可以访问创建它的外围类对象的数据域。能够实现该功能是因为内部类的对象总有一个隐式的引用,它指向了创建它的外部类对象。
  • 内部类有一个默认的编译器自动生成的构造器,因此内部类也有构造函数,在编译器编译完后,会出现(外部类名.class)和(外部类名$内部类名.class)两个可执行文件
  • 内部类是一种编译器现象,与虚拟机无关。编译器将会把内部类翻译成用 this 0(名字this$0是由编译器合成的,在自己编写的代码中不能够引用它)
  • 内部类中声明的所有静态域都必须是final。原因:我们希望一个静态域只有一个实例,不过对于一个外部对象,会分别有一个单独的内部类实例。如果这个域不是final,它可能就不是唯一的

  • 内部类不能有static方法,java语言规范对这个限制没有任何解释

public class MemberInnerClass {

    class memberInnerClass {

         static final int a = 0; //如果是static的就一定是final
         static int b = 0; //会报错

    }
}
  • 在java中内部类主要分为:成员内部类、局部内部类、匿名内部类、静态内部类

成员内部类

public class TalkingClock {
    private int interval;
    private boolean beep;
    public TalkingClock(int interval, boolean beep) {
        super();
        this.interval = interval;
        this.beep = beep;
    }

    public class TimePrinter implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            System.out.println("At the tone, the time is" + new Date());
            if(beep)
                Toolkit.getDefaultToolkit().beep();
        }

    }
}

这里写代码片

  • 成员内部类可以访问外部类的所有成员变量和方法、包括private的也可以访问。
  • 成员内部类依附于外部类,因此要先创建外部类,才能创建内部类。

局部内部类

  • 局部内部类是放在外部类的方法中的类。
  • 当一个内部类只在外部类的一个方法中创建了一次,那么这个时候就可以使用局部内部类。
public class Parcel5 {
    public Destionation destionation(String str){
        class PDestionation implements Destionation{
            private String label;
            private PDestionation(String whereTo){
                label = whereTo;
            }
            public String readLabel(){
                return label;
            }
        }
        return new PDestionation(str); 
        //在局部内部类所在的方法中返回该类的对象。在这个时候,内部类需要实现一个接口或者继承一个超类
    }

    public static void main(String[] args) {
        Parcel5 parcel5 = new Parcel5();
        Destionation d = parcel5.destionation("chenssy");
    }
}
  • 局部内部类不能使用public、protected 和private访问说明符进行声明。它的作用域被限定在声明这个局部类的块中
  • 内部类要访问外部方法中的局部变量时,该局部变量需要被修饰成final。
  • 内部类可以访问外部类中的所有成员。

匿名内部类

  • 将局部内部类的使用再深入一步。假如只创建这个类的一个对象,就可以不用命名类名,这种类被称为匿名内部类
  • 如果构造参数闭小括号后面跟一个开大括号,正在定义的就是匿名内部类。如:Person p = new Person("xiaojie"){...}
  • 由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。取而代之的是,将构造器参数传递给超类构造器,有其是在内部类实现接口的时候,不能有任何构造参数。
public void start(int interval, boolean beep){

    ActionListener listerner = new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            System.out.println("At the tonem the time is :" + new Date());
        }
    };

}
  • new ActionListene()匿名内部类,这个类或接口首先是要存在的。
  • 我们看到new ActionListener(){…}的参数表列中没有参数,当有参数的时候,如果这个参数在匿名内部类中有使用,就要使用final修饰该形参。

静态内部类

  • 什么时候使用静态内部类:在内部类不需要访问外部类对象的时候,应该使用静态内部类
  • 静态内部类中的方法和成员变量:与常规内部类不同,静态内部类可以有静态域和方法
  • 静态内部类不可以引用外部类的非静态成员和方法
  • 静态内部类的对象除了没有对生成它的外部类对象的引用特权外,与其他所有内部类完全一样

下面代码摘抄自: https://www.cnblogs.com/chenssy/p/3388487.html)

public class OuterClass {
    private String sex;
    public static String name = "chenssy";

    /**
     *静态内部类
     */
    static class InnerClass1{
        /* 在静态内部类中可以存在静态成员 */
        public static String _name1 = "chenssy_static";

        public void display(){
            /* 
             * 静态内部类只能访问外围类的静态成员变量和方法
             * 不能访问外围类的非静态成员变量和方法
             */
            System.out.println("OutClass name :" + name);
        }
    }

    /**
     * 非静态内部类
     */
    class InnerClass2{
        /* 非静态内部类中不能存在静态成员 */
        public String _name2 = "chenssy_inner";
        /* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
        public void display(){
            System.out.println("OuterClass name:" + name);
        }
    }

    /**
     * @desc 外围类方法
     * @author chenssy
     * @data 2013-10-25
     * @return void
     */
    public void display(){
        /* 外围类访问静态内部类:内部类. */
        System.out.println(InnerClass1._name1);
        /* 静态内部类 可以直接创建实例不需要依赖于外围类 */
        new InnerClass1().display();

        /* 非静态内部的创建需要依赖于外围类 */
        OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
        /* 方位非静态内部类的成员需要使用非静态内部类的实例 */
        System.out.println(inner2._name2);
        inner2.display();
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.display();
    }
}
----------------
Output:
chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy

下面是 《java核心技术》中关于静态内部类的代码

public class corejava {
    public static void main(String[] args){
        double[] nums = new double[20];
        for(int i = 0; i< nums.length;i++){
            nums[i] = Math.random() * 100;
        }

        ArrayAlg.Pair aa = ArrayAlg.minmax(nums);
        System.out.println("min=" + aa.getFirst());
        System.out.println("max=" + aa.getSecond());
    }
}

class ArrayAlg {
    public static class Pair{
        private double first;
        private double second;

        public Pair(double first, double second) {
            super();
            this.first = first;
            this.second = second;
        }
        public double getFirst() {
            return first;
        }
        public void setFirst(double first) {
            this.first = first;
        }
        public double getSecond() {
            return second;
        }
        public void setSecond(double second) {
            this.second = second;
        }

    }

    public static Pair minmax(double[] nums){
        double min = Double.POSITIVE_INFINITY;
        double max = Double.NEGATIVE_INFINITY;

        for(double i: nums){
            if(min > i )
                min = i;
            if(max < i)
                max = i;
        }
        return new Pair(min,max);
    }
}

补充:双括号初始化

利用内部类双括号初始化,假设你想构造一个数组列表,如果以后都不在使用这个数组列表,最好让它作为一个匿名列表。

public class DoubleBraceArrayList {
    public void show(List<String> friends){
        for(String s: friends){
            System.out.println(s);
        }
    }
    public static void main(String[] args){
        DoubleBraceArrayList dal = new DoubleBraceArrayList();
        //有两个{{}},外层{}表示:它是一个匿名内部类,内括号是一个构造块。
        dal.show(new ArrayList<String>(){
            {
                add("fujie");
                add("cuidapanger");
            }
        });

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值