博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linkin大话面向对象--内部类
阅读量:5976 次
发布时间:2019-06-20

本文共 9377 字,大约阅读时间需要 31 分钟。

  • 内部类说白了就是类中有类
内部类:嵌套类

外部类:宿主类

  • 内部类主要有以下作用:记住了3个字:多继承。。。
1,内部类提供了更好的封装,可以把内部类隐藏在外部类中,不允许同一个包中的其他类访问该类。
2,内部类可以访问外部类的私有数据,外部类不能访问内部类的实现细节,比如字段。
3,匿名内部类适合用于那些仅需要一次使用的类。比如在命令模式中,当需要传入一个Command对象时,使用匿名内部类将更加方便。
  • 内部类分类,主要有下面4种:
非静态内部类;静态内部类;局部内部类;匿名内部类
  • 非静态内部类
值得注意的是:外部类的上一级程序单元是包,所以他只有2个作用域:public和默认的default。

       内部类的上一级程序单元是外部类,他就有4个作用域:可以使用任意的访问控制符。

/** *  * @version 1L * @author LinkinPark * @since 2014-11-5 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^在linkin类中定义一个binger的非静态内部类,并在binger类的实例方法中直接访问linkin的实例属性 *  */public class Linkin {    private String name = "LinkinPark";    private class Binger {        private String andress = "Binger";        public String getAndress() {            return andress;        }        public void setAndress(String andress) {            this.andress = andress;        }        // 非静态内部类的实例方法        public void test() {            System.out.println("内部类中的属性" + andress);            System.out.println("外部类中的属性" + name);        }    }        //外部类的实例方法    public void test(){        Binger binger = new Binger();        binger.test();    }        public static void main(String[] args) {        Linkin linkin = new Linkin();        linkin.test();    }}

编译上面的程序,可以看到文件所在路径生成了2个class文件:

成员内部类(包括静态内部类,非静态内部类)的class总是这样子:OutClass$ InnerClass.class。

注意上面的代码:当调用非静态内部类的实例方法时,必须要有一个非静态内部类的实例,而且这个实例必须寄存在外部类实例中。

那么问题来了:若外部类字段,内部类字段,内部类方法变量同名,则具体的访问方式是怎么样的呢?

1,访问外部类的字段:外部类类名.this.字段

2,访问内部类字段:this.字段

3,访问内部类方法的局部变量:字段

代码如下:

public class Linkin {    private String name = "LinkinPark...";    private class Binger {        private String name = "Binger...";        // 非静态内部类的实例方法        public void test() {            String name = "huhu...";            System.out.println("局部变量的属性" + name);            System.out.println("内部类中的属性" + this.name);            System.out.println("外部类中的属性" + Linkin.this.name);        }    }        //外部类的实例方法    public void test(){        Binger binger = new Binger();        binger.test();    }        public static void main(String[] args) {        Linkin linkin = new Linkin();        linkin.test();    }}

  • 在外部类以内访问非静态内部类

非静态内部类对象必须寄存在外部类对象中,但是外部类对象不一定非要有非静态内部类对象寄存其中。

因此外部类对象访问非静态内部类成员时,可能非静态内部类对象就压根没存在,反过来:要是非静态内部类对象访问外部类成员时,外部类对象一定存在的。

public class Linkin {    private String name = "LinkinPark...";    private class Binger {        private String name = "Binger...";        private String huhu = "Binger...";        // 非静态内部类的实例方法        public void test() {            String name = "huhu...";            //注意了:java不允许在非静态内部类中定义静态成员:包括静态方法,静态属性,静态初始化块。。。            //static String name = "huhu...";            System.out.println("局部变量的属性" + name);            System.out.println("内部类中的属性" + this.name);            System.out.println("外部类中的属性" + Linkin.this.name);        }    }        //外部类的实例方法    public void test(){        //注意了:外部类不允许直接访问非静态内部类的实例属性,如果确实需要访问的话,必须显式new内部类对象出来        //System.out.println(huhu);        System.out.println(new Binger().huhu);        Binger binger = new Binger();        binger.test();    }        public static void main(String[] args) {        //注意了:外部类的静态成员也不可以直接使用非静态内部类,下行代码编译报错。        //new Binger();        Linkin linkin = new Linkin();        linkin.test();    }}
  • 在外部类以外访问非静态内部类
内部类不能是private修饰,否则不能访问,外部类以外的地方定义内部类变量。类型:OuterClass.InnerClass varName。

非静态内部类对象是存放在外部类的对象里的,因此在创建非静态内部类对象之前,必须先创建其外部类的对象。OuterInstance.new InnerClass([参数列表])。

class Linkin {    String name = "LinkinPark...";    class Binger {        String name = "Binger...";                public Binger(){        }                public Binger(String name){            this.name = name;        }        public void test() {            System.out.println("帝王注定孤独,江山与他何干...");        }    }    }//其实在外部类中或者外部类外创建内部类对象(比如一个子类对象),都要使得内部类保持外部类对象的一个引用。//前者可以通过外部类对象直接new内部类出来,后来将外部类作为参数传入内部类的子类构造器中。public class LinkinTest extends Linkin.Binger{        //No enclosing instance of type Linkin is available due to some intermediate constructor invocation    //下面的构造器必须在,而且还要必须传入一个外部类,因为非静态内部类对象中必须存在一个外部类对象的引用的    public LinkinTest(Linkin linkin){        linkin.super();        //linkin.super("huhu");    }    public static void main(String[] args) {        //创建内部类对象        Linkin.Binger binger = new Linkin().new Binger("忽忽");        //访问属性        System.out.println(new Linkin().name);//LinkinPark...        System.out.println(new Linkin().new Binger().name);//Binger...        System.out.println(new Linkin().new Binger("忽忽").name);//忽忽    }    }

  • 静态内部类

使用static修饰内部类,该内部类属于其外部类,而不属于外部类的实例;静态内部类可包括静态成员也可包括非静态成员。

根据静态成员不能访问非静态成员的规定,所以静态内部类不能访问外部类实例成员,只能访问外部类的静态成员。即使是静态内部类的方法也不可以。

为毛静态内部类实例方法中也不能访问外部类的实例属性?

静态内部类对象不是寄存在外部类对象中的,而是寄存在外部类的类中。如果允许上面的操作,但是找不到外部类的实例对象,肯定要引起错误的呀。

/** * * @version 1L * @author  LinkinPark  * @since   2014-11-5 * @motto   梦似烟花心似水,同学少年不言情 * @desc    ^static不可以修饰外部类,但是可以修饰内部类 */class Linkin {    String name1 = "LinkinPark...";    static String name3;    static class Binger {        String name2 = "Binger...";                public Binger(){        }                public Binger(String name2){            this.name2 = name2;        }        public void test() {            //Cannot make a static reference to the non-static field name1            //静态成员不能访问非静态成员            //System.out.println(name1);            System.out.println(name3);        }    }    }

  • 在外部类之内访问静态内部类

public class Linkin {    private String name = "LinkinPark";    private static int age = 25;    static class Binger {        private String name1 = "Binger";        private static int age1 = 24;        public void show() {            // System.out.println(name);不能访问:静态的不能访问非静态的            System.out.println(new Linkin().name);// 可以访问            System.out.println(age);// 可以访问        }    }    public void test() {        // System.out.println(name1);不能访问        // System.out.println(age1);不能访问        System.out.println(new Binger().name1);        System.out.println(Binger.age1);        new Binger().show();    }    public static void main(String[] args) {        new Linkin().test();//Binger 24 LinkinPark 25    }}

  • 在外部类以外访问静态内部类

因为静态内部类是外部类的类成员,因此在创建内部类对象时不需创建外部类的对象;

创建内部类对象:new OuterClass.InnerClass([参数列表])。注:静态内部类的全名应该是OuterClass.InnerClass,所以要看作是一个整体。

public class Linkin {    static String name3;    static class Binger {        static String name2;        public void show(){            System.out.println("静态内部类实例方法...");        }        public static void staticShow(){            System.out.println("静态内部类静态方法...");        }    }    public static void main(String[] args) {        Linkin.Binger binger = new Linkin.Binger();        Linkin.Binger.staticShow();//调用静态内部类静态方法        binger.show();//调用静态内部类的实例方法    }}

  • 局部内部类

对于局部成员而言,不管是局部变量,还是局部内部类,他们的上一级程序单元是方法,而不是类,所以使用static完全没有意义。不仅如此,因为局部成员的作用域是所在的方法,其他程序单元永远不能访问另一个方法中的局部变量,所以局部变量不可以使用访问控制符修饰。

局部内部类:定义在方法里的内部类。

特点:不能在宿主类以外的地方使用,局部内部类也不能使用访问修饰符和static修饰。

局部内部类只能访问方法中final修饰的局部变量:因为final修饰的变量相当于一个常量,其生命周期超出了方法运行的生命周期。

关于上面这一点,我也不是很懂,记住就好了。其实一般也不会在一个方法中来定义一个内部类,这个有点复杂了,就好比不会在一个接口里面定义一个内部接口,我是没见过。

public class Linkin {    public void test(){        class Binger{                    }        class Binger1{                    }    };    public static void main(String[] args) {        final int age = 0;        class Binger{            String name;            public void test(){                //注意了:局部内部类中访问局部变量必须使用final修饰那个变量                System.out.println(age);            }        }        class Binger1 extends Binger{            String name1;        }        Binger1 binger1 = new Binger1();        binger1.name = "LinkinPark...";        binger1.name1 = "binger...";        System.out.println(binger1.name+"---"+binger1.name1);    }}

编译上面的程序看到有5个class,这表明局部内部类的class文件总是以下命名方式:OutClass$InnerClass.class,注意到局部内部类的文件名的class文件比内部类的class文件多了一个数字,这是因为同一个类中不可能有2个同名的成员变量,但是同一个类中可能有2个或者2个以上的同名的局部内部类,所以java为局部内部类的class文件增加了一个数字,用于区分。

  • 匿名内部类

适合只使用一次的类。1,不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建匿名内部类的对象,2,匿名内部类不能定义构造器,因为匿名内部类没有类名。
格式:new 父类构造器([实参列表]) 或 接口()
   {
//匿名内部类的类体部分
   }
注意:匿名内部类必须继承一个父类或者实现一个接口,但最多只能一个父类或实现一个接口;

创建匿名[Anonymity]内部类时会立即创建一个该类的实例,这个类定义立即消失,匿名内部类不能重复使用。匿名内部类访问局部变量时也必须使用final修饰那个变量。

public class Linkin {    //定义一个方法,其中的参数要用到下面的抽象类    public static void test(Binger binger){        System.out.println(binger.getName());        System.out.println(binger.test());    }    //定义一个方法,其中的参数要用到下面的接口    public static void test1(Ihuhu huhu){        System.out.println(huhu.test());    }    public static void main(String[] args) {        //直接传入一个匿名内部类,只是在调用这个方法的时候使用一次        Linkin.test(new Binger(){            @Override            //这里是必须要实现的抽象方法            public String test() {                return "这里把name的get方法返回了。。。";            }                        @Override            //匿名内部类当然可以重写继承过来的方法            public String getName() {                return "linkinPark...";            }                    });                Linkin.test1(new Ihuhu(){                        @Override//必须要实现接口里面的所有的方法呀            public String test() {                return "huhu...";            }                    });    }}abstract class Binger{    private String name = "binger...";    public Binger(){            }    public Binger(String name){        this.name = name;    }        public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    //定义一个抽象方法    abstract public String test();}interface Ihuhu{    public String test();}

 

转载于:https://www.cnblogs.com/LinkinPark/p/5233156.html

你可能感兴趣的文章
node.js实现formdata上传文件
查看>>
Mac 环境下连接多个git — ssh方式
查看>>
移动端1px边框解决方案
查看>>
javascript中var、let、const声明的区别
查看>>
前端论坛、博客及公众号汇总
查看>>
你不知道的javascript事件
查看>>
【搜遍互联网,集百家之长】环境配置从入门到放弃之Mac环境下,安装XAMPP,给phpstorm安装Xdebug调试工具...
查看>>
Insert Interval
查看>>
JavaScript深入理解对象方法——Object.assign()
查看>>
京东自建数据中心核心技术解密——运营管理篇
查看>>
从尼古拉斯·泽卡斯开始学习
查看>>
javascript中关于作用域和闭包
查看>>
js的parseInt() map(),reduce()方法详解
查看>>
golang数据类型与MySQL数据类型的对应
查看>>
JDBC 4.2 Specifications 中文翻译 -- 第九章 连接
查看>>
es6的Proxy(代理)
查看>>
CentOs 7.2下ELK日志分析系统搭建
查看>>
Eclipse Modeling Framework, 2nd Edition. (EMF)学习笔记(一)——EMF介绍
查看>>
Laravel 源码解读:php artisan make:auth
查看>>
2017-06-08 前端日报
查看>>