反射和泛型(一)

通过反射获取和设置字段的私有属性(包括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,其他的都接不住。

 

猜你喜欢

转载自www.cnblogs.com/chxyshaodiao/p/12303608.html