反射(java基础)

一、反射的基础:Class

 

         1. 概述                             

             java用于描述一类事物的共性,该类事物有什么属性,没有什么属性,java程序中的各
          个java类,他们是否属于同一类事物?这个类的的名称就是Class。
             

        2. Class类:

              1. Class加载一个class,虚拟机会在内存里生成一个字节码,通过该字节码可以创建多个
             对象。    
             2.格式:
                  //Class cls1 = Person.class;
                  //Class cls2 = p1.getClass();
                  //Class cls3 = Class.forName("java.lang.String");//查询,加载字节码    

             3. 三种方式获取到的字节码是相等的

             4. 只要在源程序中出现的数据类型,都有各自的Class实例对象。例如:int[]和void

 */
	public static void main(String[] args) throws Exception{
		
		String str1 = "st1";
		Class<? extends String>  cls1 = str1.getClass();
		Class<String> cls2 = String.class;
		Class<?> cls3 = Class.forName("java.lang.String");
		System.out.println("cls1="+cls1+"\tcls2="+cls2+"\t比较结果:"+(cls1==cls2));
		System.out.println("cls1="+cls1+"\tcls3="+cls3+"\t比较结果:"+(cls1==cls3));
		
		
		
		System.out.println(cls1.isPrimitive());
		System.out.println(int.class.isPrimitive());
		System.out.println(int.class == Integer.TYPE);// 基本类型的字节码和它对应的对象的TYPE是相等的。 即int.class == Integer.TYPE;
		System.out.println(int[].class.isPrimitive());											 
		System.out.println(int[].class.isArray());
		
		
		
		Class<Void> clsv = void.class;
		System.out.println(clsv);
		

		
		
	}

二、 反射:

     * 1. 概述:

     *         反射就是把java类中的各种成分映射成对应的java类。

     * 2. 构造方法的反射应用

     *         Constructor类代表某个类中的一个构造方法

     *         得到某个类所有构造方法:

     *         eg:Constructor[]  constructors= Class.forName("java.lang.String").getConstructor();

     *         得到某一个构造方法:(获得方法时要用到类型)

     *         eg:Constructor constructor = Class.forName("java.lang.String").getConstructor("StringBuffer.class");

     *         创建实例对象:(调用方法时要用到类型)

     *             *通常方式:String str = new String(new StringBuffer("abc"));

     *             *反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));

public static void MethodDemo() throws NoSuchMethodException,
			InstantiationException, IllegalAccessException,
			InvocationTargetException {							//构造方法的反射
		//new String();
		Constructor<String> constructor = String.class.getConstructor(StringBuffer.class); //jdk1.5新特性,可变参数
		String str = constructor.newInstance(new StringBuffer("abc"));
		System.out.println(str);
	}


     * 3. 成员变量的反射应用

     *         详情见例子:

 

public static void FieldDemo() throws NoSuchFieldException,
			IllegalAccessException {
		Person person = new Person("ss","basketball",5);
		//Field personname = person.getClass().getField("name");  //getField只能访问共有的成员
		Field personname = person.getClass().getDeclaredField("name");  //getDeclaredField  无论是否公开都能看到
		personname.setAccessible(true);                                 //setAccessible:是否允许我强行获取
		//fieldname的值是ss吗?不是!!!!
		System.out.println(personname.get(person));
	}


     * 4. 成员变量案例

private static void changeString1(Object obj) throws Exception{
		Field filed = obj.getClass().getDeclaredField("hobby");  
		filed.setAccessible(true);
			if(filed.getType()==String.class){			//这里用"==",因为同一个字节码用==比较准确
				String oldValue = (String)filed.get(obj);
				String newValue = oldValue.replace('u', 'a');
				filed.set(obj, newValue);
			}
	}
	
	private static void changeString(Object obj) throws Exception{
		Field[] filed = obj.getClass().getFields();  	//获取obj内所有的成员变量
		for(Field fil : filed){
			if(fil.getType()==String.class){			//这里用"==",因为同一个字节码用==比较准确
				String oldValue = (String)fil.get(obj);
				String newValue = oldValue.replace('a', 'b');
				fil.set(obj, newValue);		
			}
		}
		
	}

三、Method类:

     1. Method基础应用

     * Method类代表某个类中的一个成员方法
     * 得到类中的某一个方法:
     * eg:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
     * 调用方式:System.out.println(str.charAt(1));
     * 反射方式:System.out.ptintln(charAt.invoke(str,1));
   

public static void main(String[] args)throws Exception {
		//str.charAt(1);
		String str = "It's my class";
		//普通调用
		System.out.println(str.charAt(1));
		//反射调用
		Method methodCharAt = String.class.getMethod("charAt",int.class);
		System.out.println(methodCharAt.invoke(str,1));
		System.out.println(methodCharAt.invoke(str,new Object[]{2}));//1.4特性   Object invoke(Object obj, Object[]) 
		 
	}

     2.main方法的反射调用

     为什么要用反射,因为我不知道这个main()方法是属于谁的 ,所以用反射
     *
     * 需求:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
     * 注意:main()方法的参数是一个字符串数组,而invoke()方法版本中,会将后面的数组当作参数打散。
     * 所以不能使用mainMethod.invoke(null,new String[]{"xxxx"});
     * 解决办法:  

                1. mainMethod.invoke(null,new Object[]{new String[]{"xxxx"}})
                2. mainMethod.invoke(null,(Object)new String[]{"cccc"});

class TestArguments{
	public static void main(String[] args){
		for(String arg : args){
			System.out.println(arg);
		}
	}
}
public class MainTest {
	/**
	 * @author Mr.z
	 * 
	 * 为什么要用反射,因为我不知道这个main()方法是属于谁的 ,所以用反射
	 * 
	 * 需求:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
	 * 
	 * 
	 * 注意:main()方法的参数是一个字符串数组,而invoke()方法版本中,会将后面的数组当作参数打散。
	 * 所以不能使用mainMethod.invoke(null,new String[]{"xxxx"});
	 * 解决办法:	1. mainMethod.invoke(null,new Object[]{new String[]{"xxxx"}})
	 * 			2. mainMethod.invoke(null,(Object)new String[]{"cccc"});
	 */
	
	public static void main(String[] args)throws Exception {
		
		//静态方式调用main方法
		TestArguments.main(new String[]{"111","222"});
		//反射方式调用
		String startingClassName = args[0];
		Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
		//mainMethod.invoke(null, new Object[]{new String[]{"123"}});
		mainMethod.invoke(null,(Object)new String[]{"123"});
		

	}

}

四、数组反射

      1、反射类型:

     *          1. 具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
     *          2. 代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
     *          3. 基本类型的一维数组可以被当作Object使用,不能作为Object[]使用。非基本类型的一维数组,既
     *         可以被当作Object使用,又能作为Object[]使用
     *          4. Arrays.asList()方法处理int[]和String[]时候,不能直接用来处理int[]

     2、数组反射的应用

import java.lang.reflect.Array;
import java.util.Arrays;

public class ArrayFelection {

	/**
	 * @author Mr.zz 
         */
	public static void main(String[] args) throws Exception {
		//ArrayTest();

		String [] str = {"aaaa","bbbb","cccc"};
		Object obj = str;
		printObject(obj);
		printObject("asdfsdfsad");

	}

	private static void printObject(Object obj) {
		Class<?> cla = obj.getClass();   //获取字节码文件
		if (cla.isArray()) {
			int lang = Array.getLength(obj);
			for (int i = 0; i < lang; i++) {
				System.out.println(Array.get(obj,i));
			}
		} else {
			System.out.println(obj);
		}

	}

	public static void ArrayTest() {
		int[] a1 = new int[] { 4, 5, 6 };
		int[] a2 = new int[4];
		int[][] a3 = new int[2][3];
		String[] a4 = new String[] { "a", "b", "c" };
		System.out.println(a1.getClass() == a2.getClass());
		Class<?> c1 = a1.getClass();
		Class<?> c3 = a3.getClass();
		Class<?> c4 = a4.getClass();
		System.out.println(c1 == c3);
		System.out.println(c1 == c4);
		System.out.println(a1.getClass().getName());
		System.out.println(a1.getClass().getSuperclass().getName());
		System.out.println(a4.getClass().getSuperclass().getName());

		// Object obj1 = a1;
		// Object obj2 = a2;
		// Object[] objError = a1; //这是错误的,因为基本数据类型不是对象
		// Object[] obj3 = a3;
		// Object[] obj4 = a4;

		System.out.println(a1);
		System.out.println(a4);
		System.out.println(Arrays.asList(a1)); // 会报错,因为int不是对象
		System.out.println(Arrays.asList(a4));
	}

五、反射的综合应用:制作框架

代码:

import com.itema.bean.ReflectPoint;

public class ReflectDemo1 {

	/**
	 * @author Mr.zz
	 * 反射的综合应用:制作框架
	 * 
	 */
	public static void main(String[] args) throws Exception {
		//HashSetDemo_Leak();
		InputStream ips = new FileInputStream("config.properties");
		Properties props = new Properties(); //等效于hashMap,但是它可以从文件中读取大量元素,而不必一个一个读取
		//从文件中读取信息
		props.load(ips);         	
		//良好的习惯:用完就关闭,避免内存泄漏
		ips.close();    
		String className = props.getProperty("className1");
		@SuppressWarnings("unchecked")
		Collection<Object> collections = (Collection<Object>)Class.forName(className).newInstance();
		ReflectPoint pt1 = new ReflectPoint(3,3);
		ReflectPoint pt2 = new ReflectPoint(5,5);
		ReflectPoint pt3 = new ReflectPoint(3,3);
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);	
		collections.add(pt1);	
		
		//pt1.y = 7;
		collections.remove(pt1); //因为pt1的hash值在存入的时候通过计算,将pt1存在了相应的区域,然后我们改变流y的值,
								 //此时pt1的hash值已经改变,此时在对应得内存hash值区域并不能找到pt1,所以此时内存发生了泄露
		
		System.out.println(collections.size());
	
	
	}
注意:要在工程目录下新建一个名为config.properties的配置文件,并输入以下代码。

      所谓框架就是被别人调用的。所以用反射调用配置文件里的信息可以方便别人修改

 className1 = java.util.ArrayList
 className1 = java.util.HashSet
  




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值