• Java 内部类学习


    内部类:在别的类中定义的类

    内部类的学习大纲:

    1.内部类分类及说明

    2.内部类的覆盖

    3.内部类的重写

    4.使用内部类的优势

    Java内部类分类:
    静态内部类(static inner class)
    成员内部类(member inner class)
    局部内部类(local inner class)
    匿名内部类(anonymous inner class)

    各个类的属性:

    静态内部类(访问方式相当于静态方法):

    a.创建静态内部类对象,不需要外部类对象。
    b.不能从静态内部类对象中访问非静态的外部类对象成员。
    c.接口中可以定义静态内部类

    创建:
    (方法一)StaticInner.Inner inner = new StaticInner.Inner();

    (方法二)import note.StaticInner.Inner;
    Inner inner = new Inner()

    成员内部类(访问方式相当于成员方法)

    能访问外部类中的全部成员变量和方法

    2.普通内部类(成员内部类):
    会得到外部类的所用成员的访问权限
    .this和.new
    .this:内部类获取外部类的对象可直接使用:OutClass.this;
    .new: 创建内部类,需要使用外部类的对象 outObj.new InnerClass();
    因为成员内部类对象需要使用外部类对象创建,所以持有该外部类对象,所以拥有外部类的所有成员访问权限。
    访问权限:
    private protected public 默认修饰内部类
    private:只可在该外部类中声明和初始化该内部类
    默认:只可在同包或者该外部类中声明和初始化内部类
    protected:只可在同包,或者外部类的子类,或者该外部类中声明和初始化内部类
    public:可在任何类中声明和初始化

    对于访问权限不够的内部类,如何在别的类中声明和访问?
    声明:可让内部类继承一个外部接口,通过外部接口对象接收内部类
    访问:在外部类中定义方法返回该内部类对象

    注意:
    a.外部类可以访问内部类的任何访问权限的成员(可以访问内部类私有成员)。
    b.普通内部类对象隐式的保存了一个引用,指向创建它的外围对象。
    c.普通内部类对象不能有static方法和static字段

    创建:要创建成员内部类就要先创建外部类(例如要想调用成员方法,必须先初始化一个对象是一样的道理)
    MemberInner.Inner memberInner = new MemberInner().new Inner(); 正确、
    //MemberInner.Inner memberInner = new MemberInner.Inner(); 错误:创建成员内部类要先创建外部类


    局部内部类
    局部内部类定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。

    像局部变量一样,不能被public, protected, private和static修饰。

    只能访问方法中定义的final类型的局部变量,也可以访问外部类中的成员变量和成员方法

    局部内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成局部内部类的实例并且调用其方法。

    使用局部内部类的理由:
    a.实现某个接口,于是可以返回对其的引用
    b.创建一个辅助的类来帮你解决问题,并且不希望这个类是公用的。
    c.局部内部类不能有访问控制权限,与局部变量相通。

    注意:
    作用域之外不能声明局部内部类。
    局部内部类其实与普通类编译都是一样的,只是在作用之外不可用而已。


    匿名内部类
    匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。

    匿名内部类隐式地继承了一个父类或者实现了一个接口。

    匿名内部类使用得比较多,通常是作为一个方法参数。

    public ParaUsb getParaUsb(String name){
    return new ParaUsb(name){

    String TAG = "OutClass -> ParaUsb:";
    String para = getName();

    @Override
    String convert() {
    return TAG + "VGA"; // + name 匿名内部类使用外部类的成员变量,该变量必须是final,否则不可用
    }
    };
    }

    注意:
    a.匿名内部类使用外部类的成员变量,该变量必须是final,否则不可用
    b.可以将外部类的成员通过构造器传给匿名内部类的基类,在该基类中通过方法返回该外部类的成员,即可访问外部类的非final成员
    c.匿名内部类与正常的继承相比,限制更大(通过构造器继承,只有一个构造器),因为匿名内部类即可以继承父类也可以实现接口,但是不能两者兼备,实现接口也只能实现一个接口。
    6.多层内部类:
    多层内部类 :一个类无论嵌套多少层内部类,该内部类能透明的访问所有它嵌入的外部类的所有成员。
    class OutClass{
    void printfOutClass();
    class InnerA{
    private String name = "A class";
    void a(){}
    class InnerB{
    private String name = "B class";
    void b(){
    a();
    printfOutClass();
    }
    }
    }
    }

    7.内部类的继承
    如果想用一个普通类去继承另一个类的内部类,必须在该普通类的构造方法里加上另一个类的引用
    因为:内部类必须要持有外部类的引用。

    class ExtendInnerClass{
    public ExtendInnerClass(OutClass outClass){
    outClass.super(); //构造函数需要连接外部类,不调用,不能通过编译器
    }
    }

    8.内部类的重写:
    class A{
    InnerA innerA;
    public A(){
    System.out.println("A");
    innerA = new InnerA();
    }

    public void printf(){
    innerA.printf();
    }

    public void insertInnerA(InnerA a){
    innerA = a;
    }

    class InnerA{
    public InnerA(){
    System.out.println("InnerA");
    }

    void printf(){
    System.out.println("InnerA");
    }
    }
    }

    /**
    * 重写内部类不起作用
    */
    class ExtendA extends A{
    public class InnerA {
    public InnerA(){
    System.out.println("ExtendA InnerA");
    }
    void printf(){
    System.out.println("ExtendA InnerA");
    }
    }
    public void printf(){
    innerA.printf();
    }
    }

    /**
    * 重写内部类并且可以使用的方式
    */
    class ExtendA2 extends A{
    public ExtendA2(){
    insertInnerA(new InnerA()); //使用继承的当前内部类替换父类中的内部类
    }
    public class InnerA extends A.InnerA{
    public InnerA(){
    System.out.println("ExtendA2 InnerA");
    }

    void printf(){
    System.out.println("ExtendA2 InnerA");
    }
    }
    public void printf(){
    innerA.printf();
    }
    }

    public class OverrideInnerClass {
    public static void main(String[] args){
    ExtendA a = new ExtendA();
    a.printf();
    ExtendA2 a2 = new ExtendA2();
    a2.printf();
    }
    }

    代码:

    package note;

    import note.StaticInner.Inner;

    /**
    * 静态内部类{@docRoot 静态内部类只能访问外部类的静态成员变量和静态方法(无论private/public)}
    * @author zhaobing
    *
    */
    class StaticInner{

    /**
    * 定义一个静态变量,让静态内部类访问
    */
    private static String name="StaticInner";

    public static void printfExternal(){
    System.out.println("external class static method");
    }

    static class Inner{
    void printf(){
    System.out.println("this is external class static member (name):" + name);
    printfExternal();
    }
    }
    }

    /**
    * 成员内部类{@docRoot 静态内部类只能访问外部类的成员变量和方法(无论private/public)}
    * @author zhaobing
    *
    */
    class MemberInner{

    private String name = "MemberInner";

    public void printfExternal(){
    System.out.println("External class method");
    }

    class Inner{

    public void printf(){
    System.out.println("this is external class member (name):" + name);
    printfExternal();
    }
    }
    }

    /**
    * 在外部类的某一方法中定义类
    * 局部内部类 {@docRoot 静外部类的成员变量和方法(无论private/public) 但访问外部类该方法中的非final变量}
    * @author zhaobing
    *
    */
    class LocalInner{

    private String name = "LocalInner";
    private int age = 10;
    private void p(){
    System.out.println("test");
    }

    public void printfExternal(){
    int b=3;
    final int c=1;

    class Inner{
    public void printf(String name){
    System.out.println(name+c+age);
    // System.out.println(name+a+age); 报错 不能访问方法中非final变量
    p();
    }
    }
    Inner inner = new Inner();
    inner.printf(name);
    System.out.println("External class method");

    }
    }

    public class InnerClassDemo {

    public static void main(String args[]){

    /**
    * 静态内部类测试
    */
    Inner staticInner=new Inner();
    staticInner.printf();
    // StaticInner.Inner inner = new StaticInner.Inner(); 也可以使用这种方式创建,这种方式创建的时候不需要import导入

    /**
    * 成员内部类测试
    */
    // MemberInner.Inner memberInner = new MemberInner.Inner(); 错误:创建成员内部类要先创建外部类
    MemberInner.Inner memberInner = new MemberInner().new Inner();
    memberInner.printf();

    /**
    * 成员内部类测试
    */
    LocalInner localInner = new LocalInner();
    localInner.printfExternal();

    /**
    * 匿名内部类
    */
    AnonymousInner anonymousInner = new AnonymousInner();
    anonymousInner.printf(new Integer(3));
    }

    }

    class AnonymousInner{

    private String name = "AnonymousInner";

    public void printf(Integer i){
    System.out.println("i:"+i);
    }

    }

  • 相关阅读:
    Win7 vs2017 WDK 1803 1809 驱动开发 出错 KMDF
    http 请求 post get 长度限制
    IO模式和IO多路复用(阻塞IO、非阻塞IO、同步IO、异步IO等概念)
    select/poll 和 epoll 比较
    centos查看端口被哪个应用端口占用命令
    mysql索引知识简单记录
    Spring钩子方法和钩子接口的使用详解
    mysql使用自增Id为什么存储比较快
    分布式Id教程
    如何配置JVM系统属性及获取方式System.getProperty("pname")
  • 原文地址:https://www.cnblogs.com/x-bing/p/4549792.html
Copyright © 2020-2023  润新知