Java 基础之内部类基本概念与特性

1、前沿

在Android开发中时常能够遇到内部类等,但总是不敢大胆的使用,本人想通过该篇技术博客来对这些类的特点和注意点做下记录,以此来保证开发出来的代码性能优秀,结构清晰。

2、分类别展示实例

2.1 内部类定义

可以将一个类的定义放在另一个类的定义内部,就是内部类。

2.2  互相访问

内部类能访问外部类对象的所有成员,即内部类自动拥有对其外围类的所有成员的访问权。

需要注意的是: 1.  普通的内部类对象隐式地保存了一个引用,该引用指向创建它的外围类的对象。

                        2. 普通内部类内部不能包含 staic数据和staic字段,更不能包含静态内部类,当然了可以访问

/**
 * Created by zxl on 2018/7/26.
 * description: 内部类特点1
 *              内部类和外部类可以互相访问,包括私有变量
 */
public class FirstInnerClass {
    private String[] arrays = new String[10];
    public FirstInnerClass(){
        for (int i=0;i<10;i++){
            arrays[i] = "数据"+i+" ";
        }
    }

    public InnerClass createInner(){
        InnerClass innerClass = new InnerClass();
        // 外部类也可以访问内部类的私有变量
        System.out.println(innerClass.num);
        return innerClass;
    }

     class InnerClass{
        private int num = 20;
        public void method(){
            // 可以发现,可以访问到外部类的私有变量
            for (String array : arrays) {
                System.out.print(array);
            }
        }
    }
}

public class Client {
    public static void main(String[] args){
        FirstInnerClass.InnerClass innerClass = new FirstInnerClass().createInner();
        innerClass.method();
        //20
        //数据0 数据1 数据2 数据3 数据4 数据5 数据6 数据7 数据8 数据9
    }
}

 指示,对于非静态内部类而言其他对象创建内部类的对象,不得不采用  .new( )语法。记住必须得使用外部类的对象来创建其内部类对象。

FirstInnerClass firstInnerClass = new FirstInnerClass();
FirstInnerClass.InnerClass innerClass1 = firstInnerClass.new InnerClass();

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

外部类.this.成员变量

外部类.this.成员方法

2.3 内部类和向上转型

     首先看下常规的向上转型吧,这样拓展是没问题的,之后可以增加接口方法来拓展功能。

public interface ClickListener {
    void onClick();
}

public class Button implements ClickListener{

    @Override
    public void onClick() {
        System.out.println(getClass().getName()+" onClick");
    }
}

public class Client {
    public static void main(String[] args){
        ClickListener clickListener = new Button();
        clickListener.onClick();
        // normal.Button onClick
    }
}

  外围无法访问私有的内部类的对象,无法获得引用的,确已是受限制的。private内部类可以组织依赖于类型的编码。除了开发程序的,客户端是无法通过拓展接口来变更。

public class SndInnerClass {
    private class MyTextView implements ClickListener{

        @Override
        public void onClick() {
            System.out.println(getClass().getName()+" onClick");
        }
    }

    public MyTextView getConnect(){
        return new MyTextView();
    }
}

public class Client {
    public static void main(String[] args){
        ClickListener clickListener = new SndInnerClass().getConnect();
        clickListener.onClick();
        // normal.SndInnerClass$MyTextView onClick
        // !由于内部类为private类型,故而不可通过 外部类.new 内部类 的方式来创建对象了
        // SndInnerClass.MyTextView 本身就无法获得,根本无法访问成员,也仅仅可通过外部类去操作返回
    }
}

2.4 内部类延展

2.4.1局部内部类

类的定义在方法的作用域内,即为局部内部类。

/**
 * Created by zxl on 2018/7/26.
 *  注意 对于如下的局部内部类,该类是属于getText()方法的,不能通过该方法以外的其他方法去获得该对象
 *       留意其作用域
 */
public class  PartInnerClass {
    public ClickListener getText(){
        class MyEditText implements ClickListener{

            @Override
            public void onClick() {
                System.out.println(getClass().getName()+" onClick");
            }
        }
        return new MyEditText();
    }
}

public class Client {
    public static void main(String[] args){
        ClickListener text = new PartInnerClass().getText();
        text.onClick();
        // normal.PartInnerClass$1MyEditText onClick
    }
}

2.4.2 匿名内部类

/**
 * Created by zxl on 2018/7/26.
 * 匿名内部类  实则是在方法里返回一个对象,该对象是继承了一个特定的类
 */
public class AnnoyInnerClass {
    /* 该类(ClickListener) 或者接口是存在的*/
    public ClickListener  connects(){
        return new ClickListener(){
            @Override
            public void onClick() {
                System.out.println(getClass().getName()+" "+" 哈哈");
            }
        };
    }
}

public class Client {
    public static void main(String[] args){
        ClickListener connects = new AnnoyInnerClass().connects();
        connects.onClick();
        // normal.AnnoyInnerClass$1  哈哈
    }
}

传参继承也是OK的

public class AnnoyInnerClass2 {
    public ClickListener showName(int x){
        return new MyAnnoyListener(x);
    }

}
class MyAnnoyListener implements ClickListener{
    private int value;
    public MyAnnoyListener(int value){
        this.value = value;
    }

    @Override
    public void onClick() {
        System.out.println(getClass().getName()+" 点击次数:"+value);
    }
}

2.4.3 嵌套类 -- 静态内部类 

 特点:1. 创建静态内部类不需要外围内的对象。也就是说不会持有外围类的引用

          2.不能从静态内部类的对象中访问非静态的外围类对象

         3. 静态内部不可使用this 引用

public class StaticInnerClass {
    private static int num = 30;
    public static class MyInnerClass{
        private static int i = 20;
        public void method(){
            System.out.println("外部类 num = "+num);
        }
        class InnerTo{
            public void showName(){
                System.out.println("外部类的外部类 num = "+num);
                System.out.println("外部类的 i = "+i);
            }
        }
    }
}

public class Client {
    public static void main(String[] args){
        StaticInnerClass.MyInnerClass myInnerClass = new StaticInnerClass.MyInnerClass();
        myInnerClass.method();
        StaticInnerClass.MyInnerClass.InnerTo innerTo = myInnerClass.new InnerTo();
        innerTo.showName();
    }
}

3、总结

最吸引人的原因,每个内部类都能独立的继承自一个实现。 也就是说弥补了类的单一继承。

讲的很好的链接: Java内部类详解

                            深入理解为什么Java中方法内定义的内部类可以访问方法中的局部变量

                            java中的内部类总结

猜你喜欢

转载自blog.csdn.net/crazyZhangxl/article/details/81213486