https://blog.csdn.net/hasser1/article/details/79384283
https://blog.csdn.net/hasser1/article/details/78699988
https://blog.csdn.net/xiaohanluo/article/details/52034127
上面都是别人家的知识点,下面总结自己家的知识点
反射的常见用法有三种:
1.查看:查看某个类的属性、方法、构造函数等
2.装载:装载指定的类到内存中
3.调用:通过输入参数调用指定的方法
下面看一个例子,查看属性、构造函数、方法等
@NoArgsConstructor
@AllArgsConstructor
class Dog{
private int id;
private String name;
final protected int age = 1;
//构造函数通过lombok注解声明
//私有方法
private void f1(){}
//保护类型方法
protected int f2(int i) {
return 0;
}
//公有方法
public String f3(String s) {
return "java反射查看类的内容";
}
}
public class MallTestApplicationTests {
@Test
public void test() {
Class<Dog> clazz = Dog.class;
//获取这个类所有的属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//输出修饰符
System.out.print(Modifier.toString(field.getModifiers()) + "\t");
//输出属性类型
System.out.print(field.getGenericType().toString() + "\t");
//输出属性名称
System.out.println(field.getName());
}
System.out.println("----------------------------");
//获取所有的方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("----------------------------------");
//得到所有的构造函数
Constructor[] constructors = clazz.getDeclaredConstructors();
//输出所有构造函数
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}
//输出结果
private int id
private class java.lang.String name
protected final int age
----------------------------
public java.lang.String com.macro.mall.test.Dog.f3(java.lang.String)
private void com.macro.mall.test.Dog.f1()
protected int com.macro.mall.test.Dog.f2(int)
----------------------------------
public com.macro.mall.test.Dog(int,java.lang.String)
public com.macro.mall.test.Dog()
在实际项目中,我们不仅应该会“查看”累的属性、方法,在更多情况下,还需要通过反射装载调用类中的方法
通过forName和newInstance方法加载类
Class.forName("com.mysql.jdbc.Driver");
这个用法我们都不陌生,jdbc连接数据库时候装载数据库驱动的代码,那这个forName的作用是装载类吗?
额!既然这么问了,答案是肯定的,不是!!!
Class.forName的作用是返回一个Class类型的对象,他一般会与newInstance方法配套使用,newInstance方法的作用才是加载类。
@Test
public void test1() {
try {
//获取Class类型的对象
Class<?> clazz = Class.forName("Dog");
//加载一个Dog类型的对象
Dog dog = (Dog) clazz.newInstance();
//调用Dog类型的方法
dog.f3("111");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
newInstance是通过java虚拟机的类加载机制把指定的类加载到内存中的。
通过反射机制调用类的方法
class Person{
private String name;
//构造函数
public Person(String name){
this.name = name;
}
public void say(String language){
System.out.println("我的名字是:" + name + "我的开发语言是:" + language);
}
public int add(int value) {
return value + 100;
}
}
@Test
public void test3() {
Class clazz = null;
Constructor constructor = null;
/**
* 通过反射调用类的构造函数创建对象
* 再用对象调用方法
*/
try {
//得到一个Class类型的对象,包含Person类的信息
clazz = Class.forName("com.macro.mall.test.Person");
//输入String.class得到Person类带参数的构造函数
constructor = clazz.getDeclaredConstructor(String.class);
//通过带参数的构造函数创建一个Person对象
Person person = (Person) constructor.newInstance("Tom");
//调用say()方法
person.say("java");
//通过clazz的getMethod()方法得到了带参say()方法的Method类型对象
Method method1 = clazz.getMethod("say", String.class);
//通过Method的invoke()调用say()方法,第一个参数指定say()方法由那个对象调用,第二个参数传入了该方法的参数
method1.invoke(person, "Python");
//通过clazz的getMethod()方法得到了带参add()方法的Method类型对象
Method method2 = clazz.getMethod("add", int.class);
//通过Method的invoke()调用add()方法,第一个参数指定add()方法由那个对象调用,第二个参数传入了该方法的参数
Object obj = method2.invoke(person, 100);
System.out.println(obj);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
输出结果:
我的名字是:Tom我的开发语言是:java
我的名字是:Tom我的开发语言是:Python
200











网友评论