什么是反射? 为什么说反射是黑魔法? 为什么要在工厂设计模式前扯反射这东西? 首先,既然在工厂设计模式前整它,肯定是在处理工厂设计模式时会用到它;既然都用黑魔法来形容它了,肯定是它异常强大; 那什么是反射嘞?既然能被称为"反",那就肯定会有"正",那,正。。。是啥子嘞?想当然,既然平时我们都不怎么搞反射,那我们平日整的就是正了呗!平时我们实例化一个对象都是是使用new关键字,例如:
Person per = new Person();
那反的自然就是不使用new关键字了嘛~ 在正式了解不使用new来实例化一个类前,我们需要先了解反射手下的几名大将(类)及它们的一些技能特效(方法使用)。
军师 -> Class类(java.lang.Class) 是不是突然眼前一亮,我好像在哪见过,好像还用过它,他不是关键字吗?怎么突然变成一个类了???是不是突然又突然发现经常用的那个class和这个Class还是有点区别的,没错,这个首字母大写了。那这个Class是干啥子的嘞? 首先让我们先看一个小demo
public class Person {
public Person() {}
@Test
public void fun() {
Class<Person> clazz = Person.class;
System.out.println(clazz);
System.out.println(clazz.getName());
}
}
输出的是:class test.reflect.Bean.Person test.reflect.Bean.Person 首先我们写了一个Person类,里面我们什么都没写,然后写了一个测试方法,通过Person.class获取了Class对象,输出后发现,就是此类的各级包路径+本类名。如果是clazz.getName则是没有了class这个头,也就是说它的Name值实际上就是test.reflect.Bean.Person。但是这个东东它有什么作用嘞?还不怎么清楚。继续再看,
public class Person {
public Person() {}
@Test
public void fun() {
Person per = new Person();
Class<? extends Person> clazz = per.getClass();
System.out.println(clazz);
System.out.println(clazz.getName());
}
}
输出的是:class test.reflect.Bean.Person test.reflect.Bean.Person 我们在测试中,首先是将Person实例化了,然后通过getClass获取到了Class对象,输出的结果是不是发现他们竟然是一样子的,是不是突然感觉他们之间有着啥不可告人的秘密~ 再看下面的一个
@Test
public void fun() {
try {
Class<?> clazz = Class.forName("test.reflect.Bean.Person");
System.out.println(clazz);
System.out.println(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
输出的是:class test.reflect.Bean.Person test.reflect.Bean.Person 是不是想,噫 ~ 这东西有啥用哇?看出来了,看出来了,他们都是一样的,但是他们有啥子用嘛! 别急,别急,有没有注意到这边开始有异常抛出了,还是ClassNotFoundException异常,所以听我继续跟你们扯
public class Person {
private String name;
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("test.reflect.Bean.Person");
Person per = (Person) clazz.getDeclaredConstructor().newInstance();
per.setName("老王");
System.out.println(per.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:老王 在这个例子中,有没有注意到,没有new关键字的出现,感觉我没有对Person对象进行实例化,但是我却调用了它的getter和setter方法,还成功输出了"老王"。但是,既然输出了老王,那也就证明了Person这个对象被实例化了。怎么实例化的?没看到,偷麽麽的,那就是反的了呗!即通过反射对这个对象进行了实例化。 首先我们先看Class类的两个方法, 方法一:getDeclaredConstructor(类<?>... parameterTypes) -> 返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。 方法二:newInstance() -> 创建由此 类对象表示的类的新实例。 看到这,你可能会想直接用newInstance()不就好了,为啥还要用上面的那个,如果你去翻看jdk的API的话你就会注意到这个方法在1.9版本就已经被废弃了,但是还可以使用,原文如下图 文档上明确表述了它的作用Creates a new instance of the class represented by this Class object以及它的用法clazz.getDeclaredConstructor().newInstance(),到此,是不是可以联想到我们之前写的三个获取类的class对象的作用了。
来再看反射手下的第二名大将 大元帅 -> Method类(java.lang.reflect.Method) 我们先来看一段代码
public class Person {
private String name;
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("test.reflect.Bean.Person");
Method[] method = clazz.getDeclaredMethods();
for(Method str:method) {
System.out.println("方法名:"+str.getName()+"\t方法类型:"+Modifier.toString(str.getModifiers())+"\t返回值类型:"+str.getReturnType());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出: 方法名:getName 方法类型:public 返回值类型:class java.lang.String 方法名:main 方法类型:public static 返回值类型:void 方法名:setName 方法类型:public 返回值类型:void
是不是感觉输出这些东西很熟悉啊!但是你可能回想,这有啥用嘛! 别急,继续看下面的一个例子:
public class Person {
private String name;
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("test.reflect.Bean.Person");
Person per = (Person) clazz.getDeclaredConstructor().newInstance();
Method[] method = clazz.getDeclaredMethods();
for(Method str:method) {
if("setName".equals(str.getName())) {
str.invoke(per, "老王");
}
}
System.out.println(per.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
看它的输出:老王 是不是感觉很神奇!到这可能还没搞清楚反射究竟是一个啥东西啊?扯了这么多,还没说明白!按照JAVA核心技术卷一的解释就是一个能分析类的能力的程序。 欲知后事如何,请看下篇黑魔法工厂的爱恨情仇 ~