定义百度百科解释
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为[动态语言]”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
API示例
1:准备了一个简单类
public class Person { //一个简单的类 private String name; private int gender; private String address; private String idCardNum; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getGender() { return gender; } public void setGender(int gender) { this.gender = gender; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getIdCardNum() { return idCardNum; } public void setIdCardNum(String idCardNum) { this.idCardNum = idCardNum; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", gender=" + gender + ", address='" + address + '\'' + ", idCardNum='" + idCardNum + '\'' + '}'; }}
2:调用示例
public class ReflectTest { private Person person; @Before public void init(){ person = new Person(); person.setName("demo"); person.setAddress("北京市天安门"); person.setGender(1); person.setIdCardNum("110000200000000000"); } @Test public void test1(){ System.out.println(person); }}
结果
console: Person{name='demo', gender=1, address='北京市天安门', idCardNum='110000200000000000'}
3:通过反射获取类名
@Testpublic void test2(){ Class c = person.getClass(); System.out.println("c.getName :"+c.getName()); System.out.println("c.getSimpleName :"+c.getSimpleName());}
结果
console: c.getName :com.example.reflect.Person c.getSimpleName :Person
4:通过反射获取类属性
@Testpublic void test3(){ Class c = person.getClass(); //获取所有字段 Field [] fields = c.getDeclaredFields(); System.out.println("all fields:"); for (Field f : fields) { f.setAccessible(true); System.out.println(f+ ":" + f.get(person)); } //获取public的字段 Field [] fields1 = c.getFields(); System.out.println("public fields:"); for (Field f : fields1) { System.out.println(f); }}
console: all fields: private java.lang.String com.example.reflect.Person.name:demo private int com.example.reflect.Person.gender:1 private java.lang.String com.example.reflect.Person.address:北京市天安门 private java.lang.String com.example.reflect.Person.idCardNum:110000200000000000 public fields:
5:获取所有方法并且执行调用
@Testpublic void test4() throws InvocationTargetException, IllegalAccessException { Class c = person.getClass(); //获取所有方法 Method [] methods = c.getDeclaredMethods(); for (Method m : methods){ //set方法需要参数 if(m.getName().startsWith("set")){ Class [] parameterTypes = m.getParameterTypes(); //我这里的方法只有一个参数,所以直接取第一个 System.out.println(m + ",parameterType is "+parameterTypes[0]); if("String".equals(parameterTypes[0].getSimpleName())){ m.invoke(person, (String)m.getDefaultValue()); }else{ m.invoke(person, 0); } }else{ //get方法具有返回值 Object result = m.invoke(person); System.out.println(m +": "+ result +", type is " + m.getReturnType()); } } System.out.println(person.toString());}
public java.lang.String com.example.reflect.Person.toString(): Person{name='demo', gender=1, address='北京市天安门', idCardNum='110000200000000000'}, type is class java.lang.Stringpublic java.lang.String com.example.reflect.Person.getAddress(): 北京市天安门, type is class java.lang.Stringpublic java.lang.String com.example.reflect.Person.getName(): demo, type is class java.lang.Stringpublic void com.example.reflect.Person.setName(java.lang.String),parameterType is class java.lang.Stringpublic void com.example.reflect.Person.setAddress(java.lang.String),parameterType is class java.lang.Stringpublic void com.example.reflect.Person.setGender(int),parameterType is intpublic void com.example.reflect.Person.setIdCardNum(java.lang.String),parameterType is class java.lang.Stringpublic int com.example.reflect.Person.getGender(): 0, type is intpublic java.lang.String com.example.reflect.Person.getIdCardNum(): null, type is class java.lang.StringPerson{name='null', gender=0, address='null', idCardNum='null'}
6:反射创建对象的方式
@Testpublic void test5() throws ClassNotFoundException, IllegalAccessException, InstantiationException { Person p1 = new Person(); //正向 System.out.println(p1.getClass()); Class c = Person.class; System.out.println(c.getName()); Class c1 = Class.forName("com.example.reflect.Person"); System.out.println(c1.getName()); Person p2 = (Person) c1.newInstance(); System.out.println(p2); }
console: class com.example.reflect.Person com.example.reflect.Person com.example.reflect.Person Person{name='null', gender=0, address='null', idCardNum='null'}
反射创建对象通常在工厂模式中比较常见,是典型的应用场景
结束语:反射是java非常重要的一个内容,java程序员应该熟悉反射的各种api和经典使用场景,反射可以创建对象,修改属性,调用方法,合理的利用反射,可以提高程序的灵活性,降低耦合性,提高自适应能力。
文章转载于:https://www.jianshu.com/p/5417df453628
原著是一个有趣的人,若有侵权,请通知删除
还没有人抢沙发呢~