反射
> 反射是指程序运行过程中动态的获取一个类信息 文件进而可以访问类中的个属性丶方法丶构造方法。
>
> 注:正射是指通过构造方法new对象,使用该对象调用属性丶方法丶构造方法。
> 类属于一个对象 Class
>
> 属性属于一个对象 Field
>
> 方法属于一个对象 Method
>
> 构造器属于一个对象 Constructor
获取类对象
```css
> 获取类对象的方式
>
> - 1. 类.class
> 2. 类.getClass()
> 3. Class.forName("包名+类名") 推荐
```java
public static void main(String[] args) throws Exception{
// 获取类对象 三种方式
// 方式 1 类.class
Class<?> p1 = Person.class;
System.out.println(p1.hashCode());
// 方式 2 类.getClass()
Person person = new Person();
Class<?> p2 = person.getClass();
System.out.println(p2.hashCode());
// 方式 3 Class.forName("包名+类名")
Class<?> p3 = Class.forName("com.niu.Person");
System.out.println(p3.hashCode());
}
通过反射获取类的构造方法和对象
> 方法:
>
> - Class.forName("包名+类名") // 通过包名+类名获取类信息
> - 类信息 . getConstructors() // 获取类所有的构造方法
> - 类信息 . getConstructor(String.class,int.class); // 获取类的指定形参列表的构造方法
> - 类信息 . getConstructor() // 获取类的无参构造
> - 指定构造方法 . newInstance() 使用构造方法将类实例化
public static void main(String[] args) throws Exception{
Class<?> class1 = Class.forName("com.niu.Person");
Constructor<?> constructor = class1.getConstructor();
Person p1 = (Person) constructor.newInstance();
System.out.println(p1.toString());
System.out.println("-----------------------------------");
Person p2 = (Person) class1.newInstance();
System.out.println(p2.toString());
System.out.println("-----------------------------------");
Constructor<?> constructor1 = class1.getConstructor(int.class, String.class);
Person p3 = (Person)constructor1.newInstance( 20,"小牛");
System.out.println(p3.toString());
System.out.println("-----------------------------------");
Constructor<?>[] constructors = class1.getConstructors();
for (Constructor<?> constructor2 : constructors) {
System.out.println(constructor2);
}
public class Person {
int id;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Person() {
System.out.println("构造方法执行了");
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
}
通过反射获取类的方法
> 方法:
>
> - 类信息 . getMethod("方法名") 获取单个的无参方法
> - 类信息 . getMethod("方法名",参数类型.class) 获取单个有参方法
> - 类信息 . getDeclaredMethod("方法名") 获取私有方法
> - 私有方法 . setAccessible(true) 设置私有方法的权限
> - 方法 . invoke(类对象 , 形参) 调用方法
> - 静态方法 . invoke(null)
> - 类信息 . getMethods() 获取所有方法
public static void main(String[] args) throws Exception{
Class<?> class1 = Class.forName("com.niu.Person");
Method eat = class1.getMethod("eat");
Person p1 = (Person) class1.newInstance();
eat.invoke(p1);
System.out.println("----------------------");
Method eat1 = class1.getMethod("eat",String.class);
eat1.invoke(p1,"嘻嘻");
System.out.println("----------------------");
Method staticMethod = class1.getMethod("staticMethod");
staticMethod.invoke(null);
System.out.println("----------------------");
Method privateMethod = class1.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(p1);
System.out.println("----------------------");
Method[] methods = class1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
}
public class Person {
int id;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Person() {
System.out.println("构造方法执行了");
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public void eat(){
System.out.println("这是一个普通无参方法");
}
public void eat(String foot){
System.out.println("这是一个普通有参参方法" + foot);
}
public static void staticMethod(){
System.out.println("这是一个静态方法");
}
private void privateMethod(){
System.out.println("这是一个私有方法");
}
}
通过反射获取类的属性
> 方法:
>
> - 类信息 . getgetFields() 获取所有公开的 继承的属性
> - 类信息 . getField("属性名") 获取单个公开的 继承的属性
> - 类信息 . getDeclaredFields() 获取所有的私有的 默认的属性
> - 类信息 . getDeclaredField("属性名") 获取单个私有的 默认的属性
> - 属性 . setAccessible(true); 设置属性的访问权限
public static void main(String[] args) throws Exception {
Class<?> class1 = Class.forName("com.niu.Person");
Field[] fields = class1.getFields();
for (Field field : fields) {
System.out.println(field.toString());
}
System.out.println("-----------------");
Field name = class1.getField("name");
System.out.println(name);
System.out.println("-----------------");
Field[] declaredFields = class1.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.toString());
}
System.out.println("-----------------");
Field salary = class1.getDeclaredField("salary");
salary.setAccessible(true);
Person p = (Person) class1.newInstance();
salary.set(p,10000.0);
System.out.println(p.getSalary());
}
public class Person {
public int id;
public String name;
int age;
private double salary;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
通过反射调用任何对象的同用方法
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);
}
public static void main(String[] args) {
Properties properties = new Properties();
invokeAny(properties, "setProperty", new Class[]{String.class, String.class}, "username", "小牛");
System.out.println(properties.toString());
}