通过反射获取和设置字段的私有属性(包括static属性)
首先建立一个类Bean作为演示类:
public class Bean { private String field; public Bean(String field) { this.field = field; } public String getField() { return field; } public void setField(String field) { this.field = field; } }
然后再建立反射的工具类:
public static void reflectionUtil(Object obj) throws IllegalAccessException { final Class<?> clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true);//设置可以获取私有字段 System.out.println(field.toString()+"\t"+field.getName()); String key = field.getName(); String value = (String) field.get(obj); if (value.equals("hello")) { field.set(obj,"hi"); } value = (String) field.get(obj); System.out.println(value);//hello } }
最后进行演示:
public static void main(String[] args) throws IllegalAccessException { Bean bean = new Bean("hello"); reflectionUtil(bean); }
输出结果为:
private java.lang.String reflection.Bean.field field
hi
通过反射调用原对象的私有方法(包括static方法)
沿用1中的bean对象,建立反射的工具类如下:
public static void invokeMethod(Object obj,String method) throws
NoSuchMethodException, InvocationTargetException, IllegalAccessException { final Class<?> clazz = obj.getClass(); final Method[] methods = clazz.getDeclaredMethods(); for(Method m:methods){ if(m.getName().equals(method)) { m.setAccessible(true); m.invoke(obj); } } }
最后进行演示:
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Bean bean = new Bean("hello,how are you!"); invokeMethod(bean,"sayHello"); }
运行结果如下:
hello,how are you!
通过反射创建原对象的实例
沿用1中的bean对象,建立反射的工具类如下:
public static Object reflectionUtil(Object obj)
throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException { final Constructor<?> constructor = obj.getClass().getConstructor(String.class); Object brother = constructor.newInstance("brother"); return brother; }
通过反射获取对象父类中的私有属性、私有方法
通过对象的class实例获取该对象的superclass实例,在superclass实例的基础上进行操作即可。
extends 和super 泛型限定符
泛型中上界和下界的定义:
上界<? extend Fruit>
下界<? super Apple>
上界和下界的特点:
上界的list只能get,不能add(确切地说不能add除null之外的对象,包括Object)
或者说<? extend Class>可以作为方法的返回值类型,但是不能作为方法的输入参数类型。
下界的list只能add,不能get
或者说<? extend Class>可以作为方法的输入参数类型,但是不能作为方法的返回值类型。
示列代码如下:
class Fruit {} class Apple extends Fruit {} class Jonathan extends Apple {} class Orange extends Fruit {}
class Fruit {}
class Apple extends Fruit {}
class Jonathan extends Apple {}
class Orange extends Fruit {}
class GoldenApple extends Apple{}
public class CovariantArrays {
public static void main(String[] args) {
//上界,允许用Fruit这一父类来接住
List<? extends Fruit> flistTop = new ArrayList<Apple>();
flistTop.add(null);
//add Fruit对象会报错
//flistTop.add(new Fruit());
Fruit fruit1 = flistTop.get(0);
//下界,允许加入Apple的子类
List<? super Apple> flistBottem = new ArrayList<Apple>();
flistBottem.add(new Jonathan());
flistBottem.add(new GoldenApple());
//get Apple对象会报错
//Apple apple = flistBottem.get(0);
}
}
//所以是遵循了里氏法则
上界<? extend Fruit> ,表示所有继承Fruit的子类,但是具体是哪个子类,无法确定,所以调用add的时候,要add什么类型,谁也不知道。但是get的时候,不管是什么子类,不管追溯多少辈,肯定有个父类是Fruit,所以,我都可以用最大的父类Fruit接着,也就是把所有的子类向上转型为Fruit。
下界<? super Apple>,表示Apple的所有父类,包括Fruit,一直可以追溯到老祖宗Object 。那么当我add的时候,我不能add Apple的父类,因为不能确定List里面存放的到底是哪个父类。但是我可以add Apple及其子类。因为不管我的子类是什么类型,它都可以向上转型为Apple及其所有的父类甚至转型为Object 。但是当我get的时候,Apple的父类这么多,我用什么接着呢,除了Object,其他的都接不住。