获取类的三个方法
在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
说白了,Class类对象就是封装了一个类的类型信息,可以通过该对象操作其对应的类,即反射机制。 也就是说,当编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息
利用对象调用getClass()方法获取该对象的Class实例
使用Class类的静态方法forName(),用类的名字获取一个Class实例
运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例
//方式一: 通过对象获得
Class c1 = person.getClass();
//方式二:通过forname获得
Class c2 = Class.forName("com.zhenlu.reflection.Student");
//方式三:通过类名。class获得
Class c3 = Student.class;
在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象
Class类的对象是通过类加载器来生成的
类加载器,也就是ClassLoader,里面有个方法叫loadClass(),通过这个方法来完成类加 载,生成某个类对应的Class对象。
通过Class对象可以完整地得到一个类的完整结构,通过一系列API
而在堆里面会产生一个类对象,它是一个数据结构,数据结构里面就会把成员变量、成员方法等当成一个对象来操作
类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法代码,变量名,方法名,访问权限等等。)
加载类过后,在方法区里面,会得到一个字节码二进制文件,具体来说就是:当我们把类加载完毕以后,除了会生成一个Class类对象在堆里面,同时在方法区还会生成类的字节码二进制数据,把这个二进制数据也称为元数据,而在堆里面会产生一个类对象,它是一个数据结构,数据结构里面就会把成员变量、成员方法等当成一个对象来操作。二进制操作起来会比较麻烦,但是对于数据结构操作起来就更方便了
package com.godairo.reflection.class_;
import com.godairo.Car;
import java.lang.reflect.Field;
/**
* @author GodAiro
* Creation Time: 2022/7/17 17:21.
* 演示Class类的一些常用方法
*/
@SuppressWarnings({"all"})
public class Class02 {
public static void main(String[] args) throws Exception {
String classAllPath = "com.godairo.Car";
//1.获取Car类对应的Class对象
//<?> 这个问号表示不确定的Java类型,也就是说将来的对象到底是表示Car还是Dog还是Person,这是不确定的,不写也可以,写也可以
Class<?> cls = Class.forName(classAllPath);
//2.输出Cls
System.out.println(cls);//显示cls对象是属于哪个类的Class对象,但是要清楚,这个cls不是一个真正的Car对象,不要有强转这个操作。
System.out.println("运行类型:"+cls.getClass()); //输出运行类型 java.lang.Class
//3.得到包名
System.out.println("包名:"+cls.getPackage().getName());
//4.得到全类名
System.out.println("类名:"+cls.getName());
//5.通过cls创建一个对象实例
Car car = (Car)cls.newInstance();
System.out.println(car);
//6.通过反射获取属性,比如想获得brand属性
Field brand = cls.getField("brand");
System.out.println("得到的属性:"+brand.get(car));//宝马
//7.通过反射给属性赋值
brand.set(car,"奔驰");
System.out.println("赋值后的属性:"+brand.get(car));//奔驰
//8.遍历得到所有属性(字段)
System.out.println("=======所有字段属性=======");
Field[] fields = cls.getFields();
for(Field f:fields){
System.out.println(f.getName());//名称
}
}
}
方法
1、toString()
public String toString() {
return (isInterface() ? "interface" : (isPrimitive() ? "" : "class")) + getName();
}
toString方法可以将对象转换为字符串,toString()首先会判断class类型是否是接口类型,也就是说普通类和接口都能用class对象来表示,然后再判断是否是基本数据类型,这里判断的都是基本的数据类型和包装类
2、toGenericString()
这个方法会返回类的全限定名称,而且包括类的修饰符合类型参数信息。
3、forName(),静态
根据类名获得一个Class对象的引用,这个方法会使类对象进行初始化。
例如 Class t = Class.forName("java.lang.Thread");能够初始化一个Thread线程对象。在java中,一共有三种获取实例的方式:
- Class.forName("java.lang.Thread")
- Thread.Class
- Thread.getClass()
4、newInstance()
创建一个类的实例,代表着这个类的对象。forName()方法对类进行初始化,newInstance方法对类进行实例化。
5、getClassLoader()
获取类加载器对象。
6、getTypeParameters()
按照声明的顺序获取对象的参数类型信息。
7、getPackage()
返回类的包
8、getInterfaces()
获得当前类实现的类或接口,可能是多个,所以返回的是Class数组。
9、Cast
把对象转换成代表类或是接口的对象
10、asSubclass(Class clazz)
把传递的类的对象转换成代表其子类的对象
11、getClasses()
返回一个数组,数组中包含该类中所有公共类和接口类的对象
12、getDeclaredClasses()
返回一个数组,数组中包含该类中所有类和接口类的对象
13、getSimpleName()
获得类的名字
14、getFields()
获得所有公有的属性对象
15、getField(String name)
获得某个公有的属性对象
16、getDeclaredField(String name)
获得某个属性对象
17、getDeclaredFields()
获得所有属性对象
18、getAnnotation(Class annotationClass)
返回该类中与参数类型匹配的公有注解对象
19、getAnnotations()
返回该类所有的公有注解对象
20、getDeclaredAnnotation(Class annotationClass)
返回该类中与参数类型匹配的所有注解对象
21、getDeclaredAnnotations()
返回该类所有的注解对象
22、getConstructor(Class...<?> parameterTypes)
获得该类中与参数类型匹配的公有构造方法
23、getConstructors)
获得该类的所有公有构造方法
24、getDeclaredConstructor(Class...<?>parameterTypes)
获得该类中与参数类型匹配的构造方法
25、getDeclaredConstructors()
获得该类所有构造方法
26、getMethod(String name,Class...<?>parameterTypes)
获得该类某个公有的方法
27、getMethods()
获得该类所有公有的方法