Java 学习笔记(8)——匿名对象与内部类

一般在编写代码时可能会遇到这样的场景——在某些时候,我需要定义并某个类,但是只会使用这一次,或者是某个类对象只会使用一次,为它们专门取名可能会显的很麻烦。为了应对这种情况,Java中允许使用匿名对象和匿名内部类的方式来解决这个矛盾

匿名对象

普通的类对象在使用时会定义一个类类型的变量,用来保存new出来的类所在的地址。而匿名类取消掉了这个变量,这个地址由编译器来处理,并且在new出来之后,它占用的内存会有JVM自动回收掉。后续无法再使用了。
例如

public class Student{
    public void classBegin(){
        System.out.println("good morning teacher!");
    }
}

new Student().classBegin();

匿名对象最常用的方式是作为函数的参数,比如上述的打印语句 "good morning teacher!" 它就是一个匿名对象,由于字符串是以对象的形式存储的,所以这里实际上就是一个没有使用对象引用的匿名对象。

当然也可以将匿名对象作为函数的返回值。

内部类

内部类的种类:成员内部类、静态内部类、局部内部类、匿名内部类

成员内部类

java中允许在一个类中定义另一个类。例如

public class Car{
    public class Engine{
        
    }
}

上述例子在Car这个类中定义了一个Engine类,那么Car就是外部类,而Engine就是内部类。

使用内部类需要注意:外部类是包含内部类的,所以内部类可以看到外部类的所有属性和方法,包括private方法。但是反过来则不行;

使用内部类主要有两种方式:

  • 在外部类中使用内部类的成员(间接使用)。这种方法一般是在外部类的方法中创建内部类的对象,并调用对象的方法
  • 直接使用:根据上面的定义,可以这样使用 `Car.Engine eng = new Car().new Engine()

比如下面的例子

public class Car{
    public class Engine{
        public void start(){
            System.out.println("引擎启动");
        }
    }

    //间接调用
    public void start(){
        System.out.println("打火");
        new Engine().start();
    }

    public static void main(String[] args){
        new Car().start();

        //直接调用
        Car.Engine engine = new Car().new Engine();
        engine.start(); 
    }
}

当外部类和内部类的成员发生命名冲突的时候在内部类中可以使用 外部类.this.成员变量 来访问外部类的成员
比如说

public class Car{
    public String type = "奥迪";
    public class Engine{
        public String type = "奥迪引擎";
        public void start(){
            System.out.println("引擎启动");
        }
        
        public void carType(){
            System.out.println(Car.this.type);
        }
    }

    //间接调用
    public void start(){
        System.out.println("打火");
        new Engine().start();
    }

    public static void main(String[] args){
        Car car = new Car();
        //直接调用
        Car.Engine engine = new Car().new Engine();
        engine.start();
        engine.carType();
        
    }
}

局部内部类

内部类不光可以直接定义在外部类中作为成员内部类,也可以定义在方法中,作为局部内部类

局部内部类也叫区域内嵌类,局部内部类与成员内部类类似,不过,区域内嵌类是定义在一个方法中的内嵌类

主要特定有:

  • 局部内部类只能在对应方法中访问,在方法外无效
  • 不能使用private,protected,public修饰符。
  • 不能包含静态成员
  • 局部内部类如果想要访问方法中的局部变量时,局部变量必须是常量。因为局部变量时分配在栈中,而局部内部类是分配在堆中的,有可能出现这样的情况,外部类的方法执行完了,内存被回收了,但是局部内部类可能还在,所以在访问局部变量时,做了一个拷贝将局部变量拷贝到局部内部类所在的堆中。为了保证数据的完整性,所以这里被拷贝的变量不允许再做修改。
public class carShow(){
    public void showCar(){
        final float price = 10000000f;
        final String type = "奔驰";

        class Car(){
            public void show(){
                System.out.println("这个车是" + type + ",售价:" + price);
            }
        }
    }
}

静态内部类

内部类如果使用static声明,则此内部类就称为静态内部类。它可以通过 外部类 . 内部类 的方式来访问。由于静态内部类是与对象无关的,在使用静态类的成员时是不需要创建对象的。所以如果想要在静态内部类中来访问外部类的成员变量,必须通过外部类的对象实例来访问。

public class Company {
    String companyNam;
    static String country;
    static class Clear{
        String name;
        public Clear() {
        }
        
        public Clear(String name) {
            super();
            this.name = name;
        }

        public void work(String name){
            String na = new Company().companyNam="联想";
            country="中国";
            System.out.println(name+"为"+na+"打扫卫生,该公司属于"+country);
        }
    }
}

匿名内部类

如果一个内部类在整个操作中只使用一次的话,就可以定义为匿名内部类。匿名内部类也就是没有名字的内部类,这是java为了方便我们编写程序而设计的一个机制,因为有时候有的内部类只需要创建一个它的对象就可以了,以后再不会用到这个类,这时候使用匿名内部类就比较合适。

匿名内部类,一般都伴随着接口一起使用比如

public interface USB{
    public abstract void open();
    public abstract void close();
}

public class Demo{
    public static void main(String[] args){
        USB usb = new USB(){
            public void open(){}
            public void close(){}
        }

        usb.open();
        usb.close();

        //使用匿名内部类的匿名对象的方式
        USB usb = new USB(){
            public void open(){}
            public void close(){}
        }.open();
    }
}

在Demo这个类的main方法中创建了一个局部的内部类,这个内部类没有名字,也就是创建了一个匿名内部类。
<hr />

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容