反射
package com.person;
/**
* @author 21115 @ date 2021/8/25
*/
// 改变值
@MyAnnotation(value = "hi")
public class Person extends Creature<String> implements Comparable<String>, MyInterface {
private String name;
int age;
public int id;
public Person() {}
@MyAnnotation(value = "abc")
private Person(String name) {
this.name = name;
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
@MyAnnotation
private String show(String nation) {
System.out.println("我的国籍是: " + nation);
return nation;
}
public String display(String interests, int age) {
return interests + age;
}
@Override
public void show() {
System.out.println("我是一个人");
}
@Override
public int compareTo(String o) {
return 0;
}
private static void showDesc() {
System.out.println("我是一个可爱的人");
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}';
}
}
package com.reflection2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
import com.person.Person;
/**
* @author 21115 @ date 2021/9/3
*/
public class ReflectionTest {
/**
* 不需要掌握
*/
@Test
public void testField() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class clazz = Person.class;
// 创建运行时类的对象,此时的 p 是一个地址:com.person.Person@22927a81
Person p = (Person)clazz.newInstance();
// 获取指定的属性,要求运行时类中的属性声明为 public
// 通常不采用此方法
// 此时 id 为:public int com.person.Person.id
Field id = clazz.getField("id");
/**
* 设置当前属性的值
*
* set():参数1:指明设置哪个对象的属性
*
* 。。。。参数2:将此属性值设置为多少
*/
id.set(p, 1001);
/**
* 获取当前属性的值
*
* get():参数1:获取哪个对象的当前属性值
*/
int pId = (int)id.get(p);
// 此时 pId 显示为:1001
System.out.println(pId);
/**
*
*/
}
/**
* 如何操作运行时类中的指定的属性 -- 需要掌握
*/
@Test
public void testField1() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class clazz = Person.class;
// 创建运行时类的对象
Person p = (Person)clazz.newInstance();
// 1.getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
Field name = clazz.getDeclaredField("name");
// 2.保证当前属性是可访问的,无论属性是 public,private 都可以加此语句
// 将 private 属性的变量变成可修改的
name.setAccessible(true);
// 3.获取、设置指定对象的此属性值
name.set(p, "Tom");
// Tom
System.out.println(name.get(p));
}
/**
* 如何操作运行时类中的指定的方法 -- 需要掌握
*/
@Test
public void testMethod()
throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Person.class;
// 创建运行时类的对象
Person p = (Person)clazz.newInstance();
/**
* 一.获取指定的某个方法
*
* getDeclaredMethod(): 参数1 : 指明获取的方法的名称
*
* 。。。。。。。。。。。。。参数2 : 知名获取的方法的形参列表
*
*/
Method show = clazz.getDeclaredMethod("show", String.class);
// 2.保证当前方法是可访问的
show.setAccessible(true);
/**
* 二、调用方法的 invoke() :参数1:方法的调用者
*
* 。。。。。。。。。。。。。。参数2:给方法形参赋值的实参 invoke() 的返回值即为对应类中调用的方法的返回值。
*/
// String nation = p.show("CHN");
Object returnValue = show.invoke(p, "CHN");
System.out.println(returnValue);
System.out.println("*** *** *** 如何调用静态方法 *** *** ***");
// private static void showDesc()
Method showDesc = clazz.getDeclaredMethod("showDesc");
showDesc.setAccessible(true);
// 如果调用的运行时类中的方法没有返回值,则此 invoke() 返回 null
Object returnVal = showDesc.invoke(Person.class);
// Object returnVal = showDesc.invoke(null);
// null
System.out.println(returnValue);
}
/**
* 如何调用运行时类中的指定的构造器
*/
@Test
public void testCConstructor()
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Person.class;
// private Person(String name)
// 1.获取指定的构造器
// getDeclaredConstructor():参数:指明构造器的参数列表
Constructor constructor = clazz.getDeclaredConstructor(String.class);
// 2.保证此构造器是可访问的
constructor.setAccessible(true);
// 3.调用此构造器创建运行时类的对象
Person per = (Person)constructor.newInstance("Tom");
// Person{name='Tom', age=0, id=0}
System.out.println(per);
}
}
/**
* 1.写出获取 Class 实例的三种常见方法
*
* 。。。Class clazz1 = String.class;
*
* 。。。Class clazz2 = person.getClass();//sout(person);//xxx.yyy.zzz.Person@...
*
* 。。。Class clazz3 = Class.forName(String classPath);//体现反射的动态性
*
*
* 2.谈谈你对 Class 类的理解
*
* 。。。Class 实例对应着加载到内容中的一个运行时类
*
*
* 3.创建 Class 对应运行时类的对象的通用方法,代码实现。以及这样操作,需要对应的运行类的构造器方面满足要求。
*
* 。。。Object obj = clazz.newInstance()://创建了对应的运行时类的对象
*
* 。。。1.必须有空参的构造器
*
* 。。。2.权限修饰符的权限要够。通常设置为 public
*
*
* 4.在工程或 module 的 src 下有名为 "jdbc.properties" 的配置文件,文件内容为:name = Tom。如何在程序中通过代码获取
*
* 5.如何调用方法 show()
*
* ..类声明如下:
*
* package.com.atguigu.java;
*
* class User{
*
* public void show(){
*
* System.out.println("我是一个中国人");
*
* } }
*
*
* User user = (User) clazz.newInstance();
*
* Method show = clazz.getDeclaredMethod("show");
*
* show.setAccessiable(true);
*
* show.invoke(user):
*/