纵有疾风起
人生不言弃

java反射机制学习笔记

定义百度百科解释

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

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » java反射机制学习笔记
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录