Class类是反射的基石,Class是一个类,封装了当前对象所对应类的信息。
此处新建一个安卓项目,新建一个MysteryBox类:
MysteryBox类代码如下:
package com.example.studyfour;
import java.util.Random;
public class MysteryBox {
private final String content;
private boolean isOpened;
public final int price;
private final String brand;
public MysteryBox(){ //无参的构造函数
this.price = 10;
this.brand = "手办盲盒";
isOpened = false;
int random = new Random().nextInt();
if (random % 100 == 1) {
content = "隐藏款";
} else {
content = "普通款";
}
}
private MysteryBox(String brand){ //有一个参数的构造函数
this.brand = brand;
this.price = 10;
isOpened = false;
int random = new Random().nextInt();
if (random % 100 == 1) {
content = "隐藏款";
} else {
content = "普通款";
}
}
public MysteryBox(int price){ //有一个参数的构造函数
this.brand = "手办盲盒";
this.price = price;
isOpened = false;
int random = new Random().nextInt();
int p = 100;
if (price > 100) {
p = 10;
}
if (random % p == 1) {
content = "隐藏款";
} else {
content = "普通款";
}
}
public MysteryBox(int price ,String brand){ //有两个个参数的构造函数
this.brand = brand;
this.price = price;
isOpened = false;
int random = new Random().nextInt();
int p = 100;
if (price > 100) {
p = 10;
}
if (random % p == 1) {
content = "隐藏款";
} else {
content = "普通款";
}
}
public void open(){
isOpened = true;
}
private void close(){
isOpened = false;
}
public String getContent() {
if (isOpened){
return content;
}
return "这个盲盒没有打开";
}
}
在此处可以进行测试,无需编译app并安装在手机上:
输出结果:
获取Class对象的方法
- 通过类名获取 类名.class
- 通过对象获取 对象.getClass()
- 通过全类名获取 Class.fromName(全类名) 或者 classLoader.loadClass(全类名)
@Test
public void getClassDemo() throws ClassNotFoundException {
//通过类直接获取
Class<?> class1 = MysteryBox.class;
System.out.println(class1);
//通过对象获取class实例
MysteryBox box = new MysteryBox();
Class <? extends MysteryBox> aClass = box.getClass();
System.out.println(aClass);
//全类名获取
Class <?> aClass1 = Class.forName("com.example.studyfour.MysteryBox");
System.out.println(aClass1);
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Class <?> aClass2 = systemClassLoader.loadClass("com.example.studyfour.MysteryBox");
System.out.println(aClass2);
}
如何判断是否为某个类的实例
⼀般情况下,使⽤ instanceof 关键字来判断是否为某个类的实例。
@Test
public void checkInstanceOf(){
MysteryBox box = new MysteryBox();
//instanceOf关键字
System.out.println(box instanceof MysteryBox);
//class.isInstance
System.out.println(MysteryBox.class.isInstance(box));
//isAssignableFrom
System.out.println(box.getClass().isAssignableFrom(MysteryBox.class));
}
创建实例
- 使⽤Class对象的newInstance()⽅法来创建Class对象对应类的实例。
- 先通过Class对象获取指定的Constructor对象,再调⽤Constructor对象的newInstance()⽅法来创建 实例。这 种⽅法可以⽤指定的构造器构造类的实例。
@Test
public void createInstance() throws Exception{
Class<?> mysteryBoxClass = MysteryBox.class;
//1.newInstance
MysteryBox box1 = (MysteryBox) mysteryBoxClass.newInstance();
System.out.println(box1.getContent());
//2.首先获取到构造器,然后实例化类实例
Constructor<?> constructor = mysteryBoxClass.getConstructor();
Object box2 = constructor.newInstance();
System.out.println(box2);
}
输出结果:
获取构造器信息
- Constructor getConstructor(Class<?>… parameterTypes)
- Constructor[] getConstructors()
- Constructor getDeclaredConstructor(Class<?>… parameterTypes)
- Constructor[] getDeclaredConstructors()
@Test
public void getConstructor() throws Exception{
//1.getConstructor
Constructor<?> constructor = MysteryBox.class.getConstructor(int.class);
System.out.println(constructor);
//2.getConstructors 获取所有的构造函数,private修饰的构造方法无法获取到
Constructor<?>[] constructors = MysteryBox.class.getConstructors();
System.out.println(Arrays.toString(constructors));
//3.获取private修饰的构造函数
Constructor<?> declaredConstructor = MysteryBox.class.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
//4.获取所有的构造函数
Constructor<?>[] declaredConstructors = MysteryBox.class.getDeclaredConstructors();
System.out.println(Arrays.toString(declaredConstructors));
}
输出结果:
获取类的成员变量
- Field getField(String name)
- Field[] getFields()
- Field getDeclaredField(String name)
- Field[] getDeclaredFields()
@Test
public void getFields() throws Exception {
MysteryBox box = new MysteryBox();
Field priceField = MysteryBox.class.getField("price"); //此处也只能拿到public修饰的属性
System.out.println(priceField.get(box));
Field[] fields = MysteryBox.class.getFields();
for (Field field: fields){
System.out.println(field.getName() + "," + field.get(box));
}
//获取private修饰的属性
Field content = MysteryBox.class.getDeclaredField("content");
content.setAccessible(true); //对于private属性我们无法直接访问,在下面content.get处会触发异常,如果想要访问则需要添加一个accessible的属性
System.out.println(box.getContent());
System.out.println(content.get(box));
Field[] declaredFields = MysteryBox.class.getDeclaredFields();
for (Field declaredField: declaredFields){
declaredField.setAccessible(true);
System.out.println(declaredField.getName() + "," + declaredField.get(box));
}
}
输出结果:
获取方法
- Method getMethod(String name, Class[] params)
- Method[] getMethods()
- Method getDeclaredMethod(String name, Class[] params)
- Method[] getDeclaredMethods()
@Test
public void getMethods() throws Exception{
MysteryBox box = new MysteryBox();
//获取public修饰的方法
Method getContent = MysteryBox.class.getMethod("getContent");
Object content = getContent.invoke(box); //主动调用getContent方法
System.out.println(content);
Method[] methods = MysteryBox.class.getMethods();
for (Method method:methods){
System.out.println(method); //打印中没有private修饰的方法
}
box.open();
System.out.println(box.getContent());
Method close = MysteryBox.class.getDeclaredMethod("close");
close.setAccessible(true);
close.invoke(box);
System.out.println(box.getContent());
Method[] declareMethods = MysteryBox.class.getDeclaredMethods(); //拿到所有的方法,包括private
for (Method method:declareMethods){
System.out.println(method);
}
}