标签:exception for 源代码 字符串类 组类型 类的属性 重新编译 substring equal
java的反射机制就是增加程序的灵活性,避免将程序写死到代码里,
例如:实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。
使用反射:
class.forName("person").newInstance();
而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,
只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。
上面提到了加载配置文件:(这里给出加载配置文件的方法)
可以使用Properties.load()来加载配置文件,加载Json或者xml
Properties properties = new Properties(); properties.load(new FileInputStream("xxx.xml")); properties.get("key");
Person类
package cn.csuft.poorguy.reflet.text; public class Person { @Name(name = "name") private String name; @Name(name = "id") private int id; @Name(name = "address") private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
Name注解:
package cn.csuft.poorguy.reflet.text; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Name { String name() default ""; }
反射机制是在[运行状态]中,(所谓运行状态中就是说在编译时程序是不知道加载内容的,在运行过程中根据配置文件得到加载信息的)
1.对于任意一个类,都能知道这个类的属性和方法
2.对于任意一个对象都能调用它的属性和方法
反射提供的功能:
在运行过程中判断任何一个对象所属的类
在运行时构造任意一个类和对象
在运行时判断一个类所具有的成员变量和方法
在运行时调用任何一个类的方法
生成动态代理
注意:使用反射的第一步必须是获取反射入口
Class clazz1 = Class.forName("cn.csuft.poorguy.reflet.text.Person"); Class clazz2 = person.getClass(); Class clazz3 = Person.class; System.out.println(clazz1.getName()); System.out.println(clazz2.getName()); System.out.println(clazz3.getName());
运行结果:
cn.csuft.poorguy.reflet.text.Person cn.csuft.poorguy.reflet.text.Person cn.csuft.poorguy.reflet.text.Person
1.获取公共方法或属性:
Person person = new Person(); Class clazz2 = person.getClass(); Method []methods = clazz2.getMethods(); for (Method method : methods) { System.out.println(method.getName()); } System.out.println("======================>"); Field []fields = clazz2.getFields(); for (Field field : fields) { System.out.println(field.getName()); }
运行结果:
getAddress getName getId setName setId setAddress wait wait wait equals toString hashCode getClass notify notifyAll ======================>
分析:我们看上面的输出结果会发现其中没有输出字段的名字,这个原因其实很简单,由于字段都是private的,所以getMethods和GetFields方法遵循访问限定符的要求
所以private类型的字段没有办法显示出来.
同时我们可以发现,多出来很多例如:wait,toString方法,并不是我们定义的,其实这些是object父类中的,所以这两个方法是得到所有的公共的方法或字段(所以父类中的也会出现)
可以使用getDeclaredFields和getDeclaredMethods方法得到当前类的所有字段或方法,其中包含了访问限定符所限制的字段和方法
Person person = new Person(); Class clazz2 = person.getClass(); Method []methods = clazz2.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName()); } System.out.println("======================>"); Field []fields = clazz2.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName()); }
运行结果:
getAddress getName getId setName setId setAddress ======================> name id address
分析:
我们可以看到使用getDeclared...得到的字段或者方法等,都是本类所自己定义的,包含了访问限定符所限制的
推荐使用第一种方法创建(构造方法),因为第二种方法在JDK1.9开始已经不推荐使用
Class clazz = Person.class; Person p = (Person)clazz.getConstructor().newInstance(); Method m = clazz.getMethod("setName",String.class); m.invoke(p,"PoorGuy"); System.out.println(p.getName());
运行结果:
PoorGuy
分析:
对上述代码中使用的方法做一个介绍
常见的方法还有:
setAccessible(true)方法的使用:
注意:这里只是说明可以这样使用,可以实现这样的功能,但是不推荐这样使用,因为破环了java的封装机制,会使得代码变的凌乱,所以没有给出这些代码的实现,推荐调用set和get方法操作字段.
Class clazz = Person.class; Annotation []ann1 = clazz.getDeclaredAnnotations(); System.out.println(ann1.length); System.out.println("=================="); Field []fields = clazz.getDeclaredFields(); for (Field field : fields) { Annotation []anno = field.getAnnotations(); System.out.println(anno[0]); }
运行结果:
0 ================== @cn.csuft.poorguy.reflet.text.Name(name=name) @cn.csuft.poorguy.reflet.text.Name(name=id) @cn.csuft.poorguy.reflet.text.Name(name=address)
注意:
在获得注解是有一些同学可能第一次发现没有得到注解,这里需要注意一些问题:
Address类:
public class Address { public String privince; public String city; public String building; public Address(String privince, String city, String building) { this.privince = privince; this.city = city; this.building = building; } public Address() { super(); // TODO Auto-generated constructor stub } @Override public String toString() { return "Address [privince=" + privince + ", city=" + city + ", building=" + building + "]"; } public String getPrivince() { return privince; } public void setPrivince(String privince) { this.privince = privince; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getBuilding() { return building; } public void setBuilding(String building) { this.building = building; } }
Person类:
public class Person { @MyElement private String name; private int age; private String sex; private ArrayList<String>friendList = new ArrayList<String>(); private Address address; public Person(String name, int age, String sex, ArrayList<String> friendList, Address address) { super(); this.name = name; this.age = age; this.sex = sex; this.friendList = friendList; this.address = address; } public Person() { super(); // TODO Auto-generated constructor stub } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public ArrayList<String> getFriendList() { return friendList; } public void setFriendList(ArrayList<String> friendList) { this.friendList = friendList; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public void addFriend(String name) { friendList.add(name); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", friendList=" + friendList + ", address=" + address + "]"; } }
主方法:
public static void main(String[] args) { Person person = new Person(); person.setName("PoorGuy"); person.setAge(18); person.setSex("男"); person.addFriend("Bob"); person.addFriend("Tom"); person.addFriend("jick"); Address address = new Address("黑龙江", "牡丹江", "幸福小区"); person.setAddress(address); System.out.println(toJson(person)); }
toJson方法:
private static String toJson(Object o) { Class clazz = o.getClass(); StringBuilder s = new StringBuilder("{"); Method []method = clazz.getDeclaredMethods(); for (Method m : method) { if(m.getName().startsWith("get")) { try { Object value = m.invoke(o); String key = m.getName().substring(3).toLowerCase(); //判断是否为整型 if(value instanceof Integer) { s.append(String.format("\"%s\":%s,",key,value)); continue; } //判断是否为字符串类型 if(value instanceof String) { s.append(String.format("\"%s\":\"%s\",",key,value)); continue; } if(value instanceof Double) { s.append(String.format("\"%s\":%s,",key,value)); continue; } if(value instanceof Float) { s.append(String.format("\"%s\":%s,",key,value)); continue; } if(value instanceof Long) { s.append(String.format("\"%s\":%s,",key,value)); continue; } //判断是否为字符串数组 if(value instanceof List) { s.append(String.format("\"%s\":[",key)); List list = (List)value; for(int i=0;i<list.size();i++) { s.append(String.format("\"%s\",",list.get(i))); } if(s.toString().endsWith(",")) { s.deleteCharAt(s.length()-1); } s.append("],"); continue; } //判断是否为字符串数组 if(value instanceof String[]) { s.append(String.format("\"%s\":[",key)); String string[] = (String[])value; for(int i=0;i<string.length;i++) { s.append(String.format("\"%s\",",string)); } if(s.toString().endsWith(",")) { s.deleteCharAt(s.length()-1); } s.append("],"); continue; } if(value instanceof Object) { s.append(String.format("\"%s\":%s,",key,toJson(value))); continue; } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } } //处理最后多余的逗号 if(s.toString().endsWith(",")) { s.deleteCharAt(s.length()-1); } s.append("}"); return s.toString(); }
运行结果:
{"address":{"building":"幸福小区","privince":"黑龙江","city":"牡丹江"},"name":"PoorGuy","friendlist":["Bob","Tom","jick"],"age":18,"sex":"男"}
注意:上述的toJson方法写的比较简单,由于时间原因没有写出所有的实现,只是写了一些简单的,便于大家对注解更加理解,只供学习使用,希望大家可以实现更多的功能,
希望大家多以指点.
反射的讲解就写这些把,希望大家可以学习到更多的知识.
标签:exception for 源代码 字符串类 组类型 类的属性 重新编译 substring equal
原文地址:https://www.cnblogs.com/PoorGuy/p/10274892.html