黑马程序员 Java高新技术-jdk1.5深入反射和泛型

用反射方式执行某个类中的main方法

写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。用普通方式调用后,为什么要用反射的方式去调用?

//反射方式调用ReflectPoint类中的额main方法
		Method method = 
ReflectPoint.class.getMethod("main", Object[].class);
		//传入的字符串数组参数封装成一个Object
		method.invoke(null, 
new Object[]{new String[]{"ffff","1111","2222"}});
		//传入的字符串数组参数封装成一个Object
		method.invoke(null,
 (Object)new String[]{"ffff","1111","2222"});

数组反射

int[] a = new int[]{1,2,3,4};
reflectArray(a);
reflectArray("fdsfdsfd");
private static void reflectArray(Object a) {
		Class array = a.getClass();
		if(array.isArray()){
			int len = Array.getLength(a);
			for(int i = 0 ;i<len;i++){
				System.out.println(Array.get(a, i));
			}
		}else{
			System.out.println(a);
		}
	}

在执行reflectArray(a)的时候有这样一个过程,由于目标方法接收的是一Object类型的参数,而传入的是一个int类型的数组,此时存在一个装箱的过程,现将int[]的数组封装成Object类型的对象,new Object[]{new int[]{1,2,3,4}}等价于new Object[]{a},此处的a为int数组类型的对象。这个动作是编译器执行的。为什么会执行这个动作 ?在调用方法的时候传入的是一个int数组,而形参接收的是一个Object对象,而在java中每一个Array都是一个Object对象。

用类加载器的方式管理资源和配置文件

加载资源的时候总是有路径的问题出现:

         绝对路径和相对路径

对于java中类加载器有两种方式,

         绝对路径加载实现config.properties

         ClassName.class.getClassLoad().getResourceAsStream(文件的绝对路径);此处文件的绝对路径是相对于ClassName这个类来说的 ,如果你的ClassName存放在com.reflect下面,那么绝对路径为:com/reflect/config.properties同时要保证该目录下面有config.properties这个配置文件存在。

         例如:InputStreaminput = ClassLoadDemo.class.getClassLoader().getResourceAsStream(

"com/reflect/demo/config.properties");

         相对路径加载config.properties

         ClassName.class.getResourceAsStream(“文件的相对路径”);此处文件的绝对路径是相对于ClassName这个类来说的 ,如果你的ClassName存放在com.reflect下面,那么绝对路径为:config.properties同时要保证该目录下面有config.properties这个配置文件存在。

         例如:InputStream input =ClassLoadDemo.class.getResourceAsStream("config.properties");

有内省引出的JavaBean

JavaBean的概念

         IntroSpectoràJavaBeanà特殊的Java类。主要是对JavaBean进行操作 。javaBean是一个特殊的java类。有一些约定规则的java类。

         一个javabean可以当作一个java类来操作 ,但是一个java类不一定能当作javabean来操作。

PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。

         PropertyDescriptorpd = new PropertyDescriptor(String propertyName,Class beanClass);

         该类中有以下两个方法:

         MethodgetReadMethod() 获得应该用于读取属性值的方法。

        Method getWriteMethod() 获得应该用于写入属性值的方法。

例:
//内省操作javaBean,获取成员X的值
		PropertyDescriptor dp1 = new PropertyDescriptor("x", rp.getClass());
		Method methodGetX = dp1.getReadMethod();
		Object x =  methodGetX.invoke(rp);
		System.out.println("x="+x);
		//内省操作javaBean,设置成员x的值
		Method methodSetX = dp1.getWriteMethod();
		methodSetX.invoke(rp, 1);
		System.out.println(rp.getX());

使用BeanUtils工具包操作JavaBean

BeanUtils是第三方提供的工具包,它可以很方便的操作javaBean。

例:

//使用BeanUtils获取属性值    

      System.out.println(BeanUtils.getProperty(rp,"x"));

      //使用BeanUtils设置值并打印出来

      BeanUtils.setProperty(rp, "x", 1000);

      System.out.println(BeanUtils.getProperty(rp,"x"));

java5的泛型

泛型中的参数信息是给编译器看的

Collection<String>collection = new ArrayList<String>();

      collection.add("text");

      collection.getClass().getMethod("add", Object.class).invoke(collection,123);

      System.out.println(collection);

在实例化容器collection的时候指定容器中装入的对象的类型是String型的,也就是说向容器中添加非String类型的数据的时候编译器在变异阶段的额时候就会报错 ,如编译此举代码的时候就会报错collection.add(123);但是通过反射技术在将文件编译成class文件的字节码的时候添加则可以顺利的通过。由此可以证明,泛型是在编译阶段,在声称字节码文件的时候会被擦除。

泛型中的术语:

整个成为ArrayList<E>泛型类

ArrayList<E>中的E成为类型变量或类型参数

ArrayList<Integer>中的Integer成为类型参数的实际类型参数

ArrayList<Integer>中的<>念typeof

ArrayList成为原是类型

3、泛型中的?通配符
?表示任意类型

使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用任何与参数化无关的方法,不能调用与参数化有关的方法。

例:

public void genericMethod(Collection<?> collection){

      collection.size();//能通过编译和正确执行

      //collection.add("fsdfds");//不能通过编译,添加元素的类型与参数化类型有关系

   }

限定通配符的上边界

Vector<? extends Number> x = newVector<Integet>(); 

限定通配符的下边界

Vector<? super Integer> x = newVector<Number>()

泛型应用示例:

public static void main(String[] args) throws Exception {
		Map<String, Integer> maps = new HashMap<String, Integer>();
		maps.put("zhangsan", 30);
		maps.put("lisi", 10);
		maps.put("wangwu", 10);
		Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();
		Iterator<Entry<String, Integer>> it = entrySet.iterator();
		while (it.hasNext()) {
			String key = it.next().getKey();
			Integer keyVal = maps.get(key);
			System.out.println(key + "::" + keyVal);
		}
	}

自定义泛型:如果一个类中的多个方法需要使用泛型,那么此泛型定义为类级别的泛型 。

静态方法不能使用类级别的泛型,因为,类级别的泛型是在对象建立之后确定哪个对象的泛型,而静态方法是不依赖于对象的就可以使用的,在泛型对象没有确定之前就使用这是错误的。

如果静态方法要使用泛型,那么必须给静态方法定义一个泛型。就像这样:

Public static <E> void method(E obj){}

通过反射技术获取泛型方法中参数的实际类型:(

public class Test extends Thread{
	
	public static void main(String[] args) throws  Exception {
		/*
		 *思路:
		 *首先获取到方法的名,然后通过ParameterizedType获取方法参数的类型和获取泛型的真实类型
		 * */
		Method method = Test.class.getDeclaredMethod("applyGeneric", Vector.class);
		Type[]  type = method.getGenericParameterTypes();
		ParameterizedType pType = (ParameterizedType)type[0];
		System.out.println(pType.getActualTypeArguments()[0]);
		System.out.println(pType.getRawType());
	}
	public static <E> void applyGeneric(Vector<Date> v){
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值