1、什么是类对象
- 类的对象:基于某个类 new 出来的对象,也称为实例对象。
- 类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
- 每个类加载到内存后都对应一个 Class对象
- 每个类有且只有一个Class对象
2、获取类对象
1、通过类的对象,获取类对象
Student s = new Student();
Class c = s.getClass();
2、通过类名获取类对象
Class c = 类名.class;
3、通过静态方法获取类对象 【推荐】
Class c = Class.forName("包名.类名");
// 获取类对象的三种方式
public static void getClazz() throws ClassNotFoundException {
// 1、使用对象获取类对象
Person zhangsan = new Person();
Class> class1 = zhangsan.getClass();
System.out.println(class1.hashCode());
// 2、使用 类名.class属性
Class> class2 = Person.class;
System.out.println(class2.hashCode());
// 3、使用 Class 的静态方法
Class> class3 = Class.forName("com.kingtl.ClassDemo.Person");
System.out.println(class3.hashCode());
}
3、反射的常用方法
方法:
// 获取类对象代表的对象
public String getName()
// 获取当前类的包
public Package getPackage()
// 获取当前类的父类
public Class super T> getSuperclass()
// 获取当前类所实现的接口
public Class>[] getInterfaces()
// 获取构造函数
public Constructor>[] getConstructors()
// 使用当前类对象创建一个实例
public T newInstance()
// 获取当前类的方法
public Method[] getMethods()
// 获取字段
public Field[] getFields()
示例代码:
Person对象类
package com.kingtl.ClassDemo;
import java.io.Serializable;
/**
* Person类
*/
public class Person implements Serializable,Cloneable {
// 姓名
private String name;
// 年龄
private int age;
public Person() {
System.out.println("无参构造执行了...");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("带参构造执行了...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// 吃
public void eat() {
System.out.println(name + "正在吃东西....");
}
// 带参的方法
public void eat(String food) {
System.out.println(name+"开始吃..."+food);
}
// 私有的方法
private void privateMethod() {
System.out.println("这是一个私有方法...");
}
// 静态方法
public static void staticMethod() {
System.out.println("这是一个静态方法....");
}
}
操作类:
package com.kingtl.ClassDemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Properties;
public class TestPerson {
public static void main(String[] args) throws Exception {
// Person zhangsan = new Person();
// zhangsan.name = "张三";
// zhangsan.eat();
// getClazz();
// reflectOpe1();
// reflectOpe2();
// reflectOpe3();
Properties properties = new Properties();
// properties.setProperty("name","zhangsan");
// System.out.println(properties.toString());
// invokeAny(properties, "setProperty", new Class[]{String.class,String.class}, "username","张三");
// System.out.println(properties.toString());
reflectOpe4();
}
// 获取类对象的三种方式
public static void getClazz() throws ClassNotFoundException {
// 1、使用对象获取类对象
Person zhangsan = new Person();
Class> class1 = zhangsan.getClass();
System.out.println(class1.hashCode());
// 2、使用 类名.class属性
Class> class2 = Person.class;
System.out.println(class2.hashCode());
// 3、使用 Class 的静态方法
Class> class3 = Class.forName("com.kingtl.ClassDemo.Person");
System.out.println(class3.hashCode());
}
// 1、使用反射获取类的名字、包名、父类、接口
public static void reflectOpe1() throws ClassNotFoundException {
// 1、获取类对象 Person
Class> class1 = Class.forName("com.kingtl.ClassDemo.Person");
// getName()
System.out.println(class1.getName());
// getPackage
System.out.println(class1.getPackage().getName());
// getSuperClass
System.out.println(class1.getSuperclass().getName());
// getInterfaces
Class>[] classes = class1.getInterfaces();
System.out.println(Arrays.toString(classes));
System.out.println(class1.getSimpleName());
System.out.println(class1.getTypeName());
}
// 2、使用反射获取类的构造方法,创建对象
public static void reflectOpe2() throws Exception {
// 1、获取类的对象
Class> class1 = Class.forName("com.kingtl.ClassDemo.Person");
// 2、获取类的构造方法getConstructor
// Constructor>[] cons = class1.getConstructors();
// for (Constructor> con : cons) {
// System.out.println(con.toString());
// }
// 3、获取类中无参构造
Constructor> con = class1.getConstructor();
Person zhangsan = (Person) con.newInstance();
System.out.println(zhangsan.toString());
// 简便方法 类对象.newInstance();
Person wangwu = (Person) class1.newInstance();
System.out.println(wangwu.toString());
// 4、获取类中的带参构造方法
Constructor> con2 = class1.getConstructor(String.class, int.class);
Person xiaoming = (Person) con2.newInstance("小明", 23);
System.out.println(xiaoming.toString());
}
// 3、使用反射获取类中的方法,并调用方法
public static void reflectOpe3() throws Exception {
// 1、获得类对象
Class> class1 = Class.forName("com.kingtl.ClassDemo.Person");
// 2、获取方法 Method对象
// 2.1 getMethods() 获取公开的方法 ,包括从父类继承的方法
// Method[] methods = class1.getMethods();
// 2.2 getDeclaredMethods() 获取类中的所有方法,包括私有的、默认、保护,不包含继承的
// Method[] methods = class1.getDeclaredMethods();
// for (Method method : methods) {
// System.out.println(method.toString());
// }
//3、获取单个方法
// 3.1 eat()
Method eatMethod = class1.getMethod("eat");
// 调用方法
Person zhangsan = (Person) class1.newInstance();
eatMethod.invoke(zhangsan);
System.out.println("--------------------");
// 3.2 toString()
Method toStringMethod = class1.getMethod("toString");
Object result = toStringMethod.invoke(zhangsan);
System.out.println(result);
System.out.println("------------");
// 3.3 带参数的eat()
Method eatMethod2 = class1.getMethod("eat", String.class);
eatMethod2.invoke(zhangsan,"苹果");
System.out.println("------------");
// 3.4 获取私有的方法
Method privateMethod = class1.getDeclaredMethod("privateMethod");
// 设置访问权限无效
privateMethod.setAccessible(true);
privateMethod.invoke(zhangsan);
// 3.5 获取静态方法
Method staticMethod = class1.getMethod("staticMethod");
staticMethod.invoke(null);
}
/**
* // 4、使用反射实现一个可以调用任何对象方法的通用方法
* @param obj 对象,表示可以调用任何对象
* @param methodName 这个对象的哪个方法,方法名
* @param types 方法的参数
* @param args 参数的值
* @return
* @throws Exception
*/
public static Object invokeAny(Object obj, String methodName, Class>[] types, Object... args) throws Exception {
// 获取类对象
Class> class1 = obj.getClass();
// 获取方法
Method method = class1.getMethod(methodName, types);
// 调用
return method.invoke(obj, args);
}
// 5、使用反射获取类中的属性
public static void reflectOpe4() throws Exception {
// 1、获取类对象
Class> class1 = Class.forName("com.kingtl.ClassDemo.Person");
// 2、获取属性(字段)公开的字段、父类继承的字段
// Field[] fields = class1.getFields();
// getDeclaredFields() 获取所有的属性,包括私有、保护、默认的,不包含继承的
// Field[] fields = class1.getDeclaredFields();
// System.out.println(fields.length);
// for (Field field : fields) {
// System.out.println(field.toString());
// }
// 3、获取 name 属性
Field nameField = class1.getDeclaredField("name");
nameField.setAccessible(true);
// 4、赋值 获取值
Person zhangsan = (Person) class1.newInstance();
nameField.set(zhangsan,"张三"); // 相当于 zhangsan.name = "张三";
// 5、获取值
System.out.println(nameField.get(zhangsan)); // zhangsan.name
}
}
4、反射中私有方法或属性如何取
需要设置访问权限
setAccessible(true)
// 3.4 获取私有的方法
Method privateMethod = class1.getDeclaredMethod("privateMethod");
// 设置访问权限无效
privateMethod.setAccessible(true);
privateMethod.invoke(zhangsan);
// 3、获取 name 属性
Field nameField = class1.getDeclaredField("name");
nameField.setAccessible(true);
// 4、赋值 获取值
Person zhangsan = (Person) class1.newInstance();
nameField.set(zhangsan,"张三"); // 相当于 zhangsan.name = "张三";
// 5、获取值
System.out.println(nameField.get(zhangsan)); // zhangsan.name