反射 p2 Class类
Class类
基本介绍
- Class也是类,因此也继承Object类;
- Class类对象不是new出来的,而是系统创建的;
- 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次;
- 每个类的实例都会记得自己是由哪个Class实例所生成的;
- 通过Class对象可以完整的得到一个类的完整结构,通过一系列API;
- Class对象是存放在堆中的;
- 类的字节码二进制数据,是存放在方法区的,有的地方称为类的元数据(包括方法代码,变量名,方法名,访问权限等等);【https://www.zhihu.com/question/38496907】
Class类的常用方法
方法名 | 功能说明 |
---|---|
static Class forName(String name) | 返回指定类名 name 的 Class对象 |
Object newInstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类、基本类型等)名称 |
Class[] getInterfaces() | 获取当前CLass对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Class gerSuperclass() | 返回表示此Class所表示的实体的父类的Class |
ConStructor[] gerConstructors() | 返回一个包含某些Constructor对象的数组 |
Field[] getDeclaredFields() | 返回Field对象的一个数组 |
Method gerMethod(String name, Class ... paramTypes) | 返回一个Method对象,此对象的形参为paramType |
-
代码演示
Car类:
package com.hspedu; /** * @author: 86199 * @date: 2023/5/22 10:27 * @description: */ public class Car { public String brand = "宝马"; public int price = 500000; public String color = "白色"; @Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", price=" + price + ", color='" + color + '\'' + '}'; } }
Class02:
package com.hspedu.class_; import com.hspedu.Car; import java.lang.reflect.Field; /** * @author: 86199 * @date: 2023/5/22 10:28 * @description: 演示Class类的常用方法 */ public class Class02 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { String classAllPath = "com.hspedu.Car"; //1. 获取到Car类 对应的Class对象 //<?> 表示不确定java类型 Class<?> aClass = Class.forName(classAllPath); //2. 输出 aClass System.out.println(aClass);//显示 aClass 是哪个类的Class对象 com.hspedu.Car System.out.println(aClass.getClass());//输出 aClass 的运行类型 java.lang.Class //3. 得到包名 System.out.println(aClass.getPackage().getName());//com.hspedu //4. 得到全类名 System.out.println(aClass.getName());//com.hspedu.Car //5. 通过 aClass 生成对象实例 Car car = (Car) aClass.newInstance(); System.out.println(car); //6. 通过反射获取属性 brand Field brand = aClass.getField("brand"); System.out.println(brand.get(car)); //7. 通过反射给字段赋值 brand.set(car, "奔驰"); System.out.println(brand.get(car)); //8. 得到所有的属性 Field[] fields = aClass.getFields(); for (Field field: fields) { System.out.println(field.get(car)); } } }
获取Class类对象
获取Class对象的6种方式:
-
前提:已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法 forName()获取,可能抛出ClassNotFoundException。实例:
Class cls1 = Class.forName("java.lang.String");
应用场景:多用于配置文件,读取类全路径,加载类。
-
前提:若已知具体的类,同通过类的class获取,该方式最为安全可靠,程序性能也最高。实例:
Class cls2 = Cat.class;
应用场景:多用于参数传递,比如通过反射得到对应构造器对象。
-
前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象。实例:
Class cls3 = 对象.getClass();//运行类型
,所以说查看运行类型就是获取该对象关联的Class对象,查看其代表的类型应用场景:通过创建好的对象,获取Class对象。
-
其他方式:通过类加载器【4种】来获取到类的Class对象
也就是说从一个类里获得类加载器可以用来加载出其他类//(1)先得到类加载器 ClassLoader classLoader = 对象.getClass().getClassLoader(); //(2)通过类加载器得到Class对象 Class cls4 = classLoader.loadClass("类的全类名");
弹幕摘要:
- 这种方法就是比第三种绕了一大圈;
- 从一个类里获得类加载器可以用来加载出其他类,这只是告诉你可以通过类加载器方式获得类对象,不是让你一定要这么做,只是告诉你有这种方式;
-
基本数据类型(int, char, boolean, float, double, byte, long, short) 按如下方式得到Class类对象
Class cls = 基本数据类型.class;
-
基本数据类型的包装类,可以通过.TYPE 得到Class类对象
Class cls = 包装类.TYPE
代码演示:
package com.hspedu.class_;
import com.hspedu.Car;
/**
* @author: 86199
* @date: 2023/5/22 11:13
* @description: 演示获取Class对象的各种方式
*/
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException {
//1. Class.forName
String classAllPath = "com.hspedu.Car";//通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println("cls1 = " + cls1);
//2. 类名.class
Class cls2 = Car.class;
System.out.println("cls2 = " + cls2);
//3. 对象.getClass(),应用场景,有对象实例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println("cls3 = " + cls3);
//4. 通过类加载器【4种】来获取到类的Class对象
//这种方法就是比第三种绕了一大圈,从一个类里获得类加载器可以用来加载出其他类
//这只是告诉你可以通过类加载器方式获得类对象,不是让你一定要这么做,只是告诉你有这种方式
//(1)先得到类加载器
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到Class对象
Class cls4 = classLoader.loadClass(classAllPath);
Class<?> aClass = classLoader.loadClass("java.lang.String");
System.out.println("cls4 = " + cls4);
System.out.println(aClass);
//cls1,cla2,cls3, cls4 都是同一个对象
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode());
//5. 基本数据类型(int, char, boolean, float, double, byte, long, short) 按如下方式得到Class类对象
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
System.out.println(integerClass);
//6. 基本数据类型的包装类,可以通过.TYPE 得到Class类对象
Class<Integer> type1 = Integer.TYPE;
Class<Character> type2 = Character.TYPE;
System.out.println(type1);
System.out.println(integerClass.hashCode());
System.out.println(type1.hashCode());
}
}
/* 运行结果
cls1 = class com.hspedu.Car
cls2 = class com.hspedu.Car
cls3 = class com.hspedu.Car
cls4 = class com.hspedu.Car
class java.lang.String
460141958
460141958
460141958
460141958
int
int
1163157884
1163157884
*/
哪些类型有Class对象
- 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
- Interface接口
- 数组
- enum枚举
- annotation注解
- 基本数据类型
- void
-
代码演示:
package com.hspedu.class_; import java.io.Serializable; /** * @author: 86199 * @date: 2023/5/23 16:42 * @description: */ public class AllTypeClass { public static void main(String[] args) { Class<String> cls1 = String.class;//外部类 Class<Serializable> cls2 = Serializable.class;//接口 Class<float[]> cls3 = float[].class;//数组 Class<float[][]> cls4 = float[][].class;//二维数组 Class<Thread.State> cls5 = Thread.State.class;//枚举 Class<Deprecated> cls6 = Deprecated.class;//注解 Class<Long> cls7 = long.class;//基本数据类型 Class<Void> cls8 = void.class;//void Class<Class> cls9 = Class.class;//Class类 System.out.println(cls1); System.out.println(cls2); System.out.println(cls3); System.out.println(cls4); System.out.println(cls5); System.out.println(cls6); System.out.println(cls7); System.out.println(cls8); System.out.println(cls9); } } /* 运行结果 class java.lang.String interface java.io.Serializable class [F class [[F class java.lang.Thread$State interface java.lang.Deprecated long void class java.lang.Class */