浅理解Java中的匿名对象

427 阅读3分钟

匿名对象

顾名思义,匿名对象指的就是没有名字的对象,在使用中理解为实例化一个类对象,但是并不把它赋给一个对应的类变量,而是直接使用。在理解匿名对象前,我们先创建一个类便于后面的使用。

class Student{
    String name;

    public void showInfo(){
        System.out.println("Name is: " + this.name);
    }
}

匿名对象具有以下特征:

  • 语法上:只创建对象,但不用变量来接收,例如:假设现在Student类如上所示,通常情况我们在使用这个类时需要先实例化类对象,然后调用类的属性和方法

    Student s = new Student();
    s.name = "Forlogen";
    s.showInfo();  // Forlogen
    

    而匿名类并不使用变量接收直接使用

    System.out.println(new Student().name)
    
  • 匿名对象的使用:

    • 匿名对象本质上仍然是一个对象,所以它具备对象的所有功能

    • 每次创建一个匿名对象都是一起全新的对象,即每次创建的匿名对象都是不同的对象,它们在堆内存中具有不同的地址。而且一个匿名对象只能使用一次。这怎么理解呢?同样假设现在想使用Student这个类,每次实例化匿名对象得到的都是新的对象:

      // 第一个匿名对象
      public class AnonymousTest {
          public static void main(String[] args) {
              System.out.println(new Student().name = "Kobe");  // Kobe
              System.out.println(new Student().name);  // null
          }
      

      从输出中可以看出,前后两个实例化的匿名对象是不同的,第一个我们为其进行赋值,打印出的就是赋值的结果;而第二个并没有对name属性就行赋值,那么返回的就是String类型的默认值null。

    既然匿名对象只能使用一次,那么它有哪些应用场景呢?常用到匿名对象的场景有如下几个:

    • 只想调用匿名对象的方法,例如在使用Scanner类获取键盘输入时,我们常这样做:

      Scanner sc = new Scanner(System.in);  // 10
      int num = sc.nextInt();  
      System.out.println(num); //10
      

      而如果只想输出从键盘获取的值,就可以使用匿名对象

      System.out.println(new Scanner(System.in).nextInt());
      
    • 直接使用匿名对象作为方法的参数和返回值

      // 将匿名对象作为返回值
      public class AnonymousTest {
          public static void main(String[] args) {
              int n = getScanner().nextInt();
              System.out.println(n);
          }
      
          public static Scanner getScanner(){
              return new Scanner(System.in);
          }
      }
      
      // 将匿名对象作为函数参数
      public class AnonymousTest {
          public static void main(String[] args) {
              Scanner sc1 = new Scanner(System.in);
              getScanner(sc1);
      
          }
      
          public static void getScanner(Scanner sc){
              System.out.println(sc.nextInt());
          }
      }
      

缺点: 一个匿名对象只能使用一次,造成内存空间的浪费。


在这里插入图片描述

如上所示,当我们依次实例化三个Student类的匿名对象时,每次实例化一个匿名对象,JVM就要在堆中为其开辟一块新的空间,当这行代码执行完毕内存就会被回收;然后再实例化新的对象时 ,JVM又会为其开辟新的空间,其他类似。

优点:

  • 由于匿名对象不需要在实例化后赋给变量,因此当大量需要使用匿名对象时,可以节省保存变量所需的栈空间
  • JVM的垃圾回收会根据对象是否可达来判断是否为垃圾,如果不可达,则在下一次的垃圾回收中进行回收。而匿名对象创建后只能使用一次,当使用结束后它就是垃圾了,这样便于JVM快速回收,节省堆内存空间。

实验代码:

package com.company;

import java.util.Scanner;

class Student{
    String name;

    public void showInfo(){
        System.out.println("Name is: " + this.name);
    }
}

public class AnonymousTest {
    public static void main(String[] args) {
        Student s = new Student();
        s.name = "Forlogen";
        s.showInfo();

        System.out.println(new Student().name = "Kobe");
        System.out.println(new Student().name);

        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        System.out.println(num);

        System.out.println(new Scanner(System.in).nextInt());
        int n = returnScanner().nextInt();
        System.out.println(n);

        Scanner sc1 = new Scanner(System.in);
        getScanner(sc1);

    }

    public static Scanner returnScanner(){
        return new Scanner(System.in);
    }

    public static void getScanner(Scanner sc){
        System.out.println(sc.nextInt());
    }
}