【注释和反射】获取class类实例的方法

目录

一、获取一个类的Class对象的几种方法

代码

二、哪些类型可以有Class对象?

代码


一、获取一个类的Class对象的几种方法

Class对象是访问类元数据的入口,通过它可以获取类的名称、方法、字段、构造器、注解等信息,还可以创建类的实例、调用方法等。

在Java中,获取一个类的Class对象主要有以下几种方式:

(1)使用.class语法: 对于任何类型(包括基本类型)的变量,都可以使用.class来获取其Class对象。

(2)使用对象的getClass()方法: 如果你有一个对象,你可以调用它的getClass()方法来获取它的Class对象。

(3)使用Class.forName()方法: 如果你知道类的全名(包括包名),你可以使用Class.forName()方法来获取其Class对象。这种方式通常用于动态加载类。

(4)使用对象的getSuperclass()方法:一个已经存在的Class对象,代表某个类的类型。调用getSuperclass()方法会返回表示该类父类的Class对象。如果该类没有显式地继承其他类,那么它隐式地继承自java.lang.Object类,因此getSuperclass()方法将返回Object类的Class对象。

(5)使用基本类型的包装类中的TYPE字段: 对于基本类型,它们的包装类都有一个名为TYPE的静态字段,该字段是该基本类型的Class对象。

注意:int.classInteger.class是不同的,前者是基本类型的Class对象,后者是包装类的Class对象。

代码

在这个代码中,展示了获取一个类的Class对象的几种方法,并调用了c4.hashCode()方法,这会返回c4对象(即表示父类的Class对象)的哈希码。哈希码通常用于在哈希表等数据结构中快速定位对象。

每个对象的哈希码在对象的生命周期内应该保持一致,并且不同的对象根据equals()方法的比较结果,可能拥有相同的哈希码(这种情况称为哈希冲突)。 

public class Test {
  public static void main(String[] args) throws ClassNotFoundException {
    Person person = new Student();
    System.out.println(person.name);

    Class c1 = person.getClass();
    System.out.println(c1.hashCode());

    Class c2 = Student.class;
    System.out.println(c2.hashCode());

    Class c3 = Class.forName("com.itheima.sjms.Student");
    System.out.println(c3.hashCode());

    Class c4 = c1.getSuperclass();
    System.out.println(c4.hashCode());

    Class c5 = Person.class;
    System.out.println(c5.hashCode());

    Class c6 = Integer.TYPE;
    System.out.println(c6.hashCode());

  }
}

class Person{
  String name;
  public Person(String name){
    this.name = name;
  }

  public Person() {
  }

  @Override
  public String toString() {
    return "Person{" +
      "name='" + name + '\'' +
      '}';
  }
}

class Student extends Person{
  public Student() {
    this.name = "学生";
  }
}

class Teacher extends Person{
  public Teacher() {
    this.name = "老师";
  }
}

总结:在Java中,获取Class对象的方式主要有.class语法、对象的getClass()方法、Class.forName()方法以及基本类型的包装类中的TYPE字段(但通常我们使用.class语法来获取基本类型的Class对象)。

  • 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
  • 已知某个类的实例,调用该实例的getClass()方法获取Class对象
  • 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException
  • 内置基本数据类型可以直接用类名.Type
  • 还可以利用ClassLoader

二、哪些类型可以有Class对象?

Class对象是访问类元数据的入口,通过它可以获取类的名称、方法、字段、构造器、注解等信息,还可以创建类的实例、调用方法等。

在Java中,几乎所有类型都可以有对应的Class对象。这些类型包括:

代码

在这个代码中,展示了可以有Class对象的一些类型,

  1. 普通类(包括内部类和匿名类): 每个加载到JVM中的普通类都会有一个对应的Class对象。这包括顶层类、嵌套类(静态内部类)和非静态内部类。

  2. 接口: 接口也有对应的Class对象。虽然接口不能实例化,但它们的Class对象描述了接口的结构,包括方法签名等。

  3. 数组: 数组在Java中是对象,并且每种数组类型都有其对应的Class对象。例如,int[].classString[].class分别表示整型数组和字符串数组的Class对象。

  4. 基本类型: 虽然基本类型(如intcharboolean等)不是对象,但Java为每种基本类型提供了包装类(如IntegerCharacterBoolean等),并且每种基本类型都有其对应的Class对象,如int.class。不过要注意,这里的int.class实际上是一个特殊语法,因为基本类型本身不是类。这种语法是为了在反射时能够方便地获取基本类型的Class对象。

  5. 枚举: 枚举类型在Java中是特殊的类,每个枚举类型都有一个Class对象。

  6. 注解类型: 注解也是一种特殊的接口,它们也有自己的Class对象。

  7. oid类型void类型也有对应的Class对象,即void.class。虽然void类型表示无返回值,但在反射中有时需要表示方法的返回类型为void

  8. 泛型类型: 泛型类型本身在运行时由于类型擦除不会有特定的Class对象。但是,你可以获取表示泛型边界或泛型超类的Class对象。例如,List<String>.class这样的表达式是不合法的,但你可以获取List.class并通过反射来检查其泛型信息(尽管这些信息在运行时是受限的)。

import scala.Int;
import java.lang.annotation.ElementType;

public class Test {
  public static void main(String[] args){
    test2();

  }

  public static void test2(){
    Class c1 = Object.class;  // 类
    Class c2 = int[].class;  // 一维数组
    Class c3 = String[][].class;  // 二维数组
    Class c4 = void.class;  // void
    Class c5 = Override.class;  // 注解
    Class c6 = Integer.class;  // 基本数据类型
    Class c7 = Class.class;  // Class
    Class c8 = ElementType.class;  // 枚举
    Class c9 = Comparable.class;  // 接口
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c3);
    System.out.println(c4);
    System.out.println(c5);
    System.out.println(c6);
    System.out.println(c7);
    System.out.println(c8);
    System.out.println(c9);
  }


  public static void test1() throws ClassNotFoundException {
    Person person = new Student();
    System.out.println(person.name);

    Class c1 = person.getClass();
    System.out.println(c1.hashCode());

    Class c2 = Student.class;
    System.out.println(c2.hashCode());

    Class c3 = Class.forName("com.itheima.sjms.Student");
    System.out.println(c3.hashCode());

    Class c4 = c1.getSuperclass();
    System.out.println(c4.hashCode());

    Class c5 = Person.class;
    System.out.println(c5.hashCode());

    Class c6 = Integer.TYPE;
    System.out.println(c6.hashCode());
  }
}

class Person{
  String name;
  public Person(String name){
    this.name = name;
  }

  public Person() {
  }

  @Override
  public String toString() {
    return "Person{" +
      "name='" + name + '\'' +
      '}';
  }
}

class Student extends Person{
  public Student() {
    this.name = "学生";
  }
}

class Teacher extends Person{
  public Teacher() {
    this.name = "老师";
  }
}

同时,我们也可以看到,两个长度不一样的数组,只要它们类型一(,此处都是int类型),那么它们的哈希code,也就是它们底层的Class类依旧是一样的,和数组的长度无关。

int[] arr1 = new int[10];
int[] arr2 = new int[100];
System.out.println(arr1.getClass().hashCode());
System.out.println(arr2.getClass().hashCode());

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值