目录
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.class和Integer.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对象是访问类元数据的入口,通过它可以获取类的名称、方法、字段、构造器、注解等信息,还可以创建类的实例、调用方法等。
在Java中,几乎所有类型都可以有对应的Class对象。这些类型包括:
在这个代码中,展示了可以有Class对象的一些类型,
普通类(包括内部类和匿名类): 每个加载到JVM中的普通类都会有一个对应的Class对象。这包括顶层类、嵌套类(静态内部类)和非静态内部类。
接口: 接口也有对应的Class对象。虽然接口不能实例化,但它们的Class对象描述了接口的结构,包括方法签名等。
数组: 数组在Java中是对象,并且每种数组类型都有其对应的Class对象。例如,int[].class和String[].class分别表示整型数组和字符串数组的Class对象。
基本类型: 虽然基本类型(如int、char、boolean等)不是对象,但Java为每种基本类型提供了包装类(如Integer、Character、Boolean等),并且每种基本类型都有其对应的Class对象,如int.class。不过要注意,这里的int.class实际上是一个特殊语法,因为基本类型本身不是类。这种语法是为了在反射时能够方便地获取基本类型的Class对象。
枚举: 枚举类型在Java中是特殊的类,每个枚举类型都有一个Class对象。
注解类型: 注解也是一种特殊的接口,它们也有自己的Class对象。
oid类型: void类型也有对应的Class对象,即void.class。虽然void类型表示无返回值,但在反射中有时需要表示方法的返回类型为void。
泛型类型: 泛型类型本身在运行时由于类型擦除不会有特定的Class对象。但是,你可以获取表示泛型边界或泛型超类的Class对象。例如,List这样的表达式是不合法的,但你可以获取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());
