黑马程序员_【总结】_ 高新_1_反射知识梳理

本文深入探讨了Java和Android开发的核心技术,包括反射机制、泛型、数组操作及高级编程特性,如for循环、可变参数、自动封装箱等。通过实例演示,详细解释了如何利用反射获取类的构造方法、成员变量和方法,以及如何进行数组和泛型的反射操作。此外,文章还涵盖了Java 1.5新特性的应用,如静态导入、享元模式和枚举类型,旨在为开发者提供全面的技术指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射知识梳理


---------- android培训 java培训、期待与您交流! ---------- 

---------------------------------------------------------------------------------------------------------------------------------------------
1、反射: 简单说就把Java类中的各种成份映射成相应的Java类
2、方法摘要:
1、Class.forName("xxx");  返回xxx 的字节码对象
3、newInstance() 通过该方法创建实例对象
3、暴力反射:
getDeclaredField("y");//  强制可读
field2.setAccessible(true);//强制可写
3、反射:构造方法:
1、getDeclaredConstructors()返回 所有构造方法
2、getConstructor(xxx) 返回指定构造方法

4、反射:成员变量:
1、getDeclaredFields() 返回所有成员变量, 包括公共,私有
2、getField("y")       返回指定成员变量

5、反射:方法:
1、getDeclaredMethods 返回所有方法
2、获取字节码对象后,用Object 对象接收 字节码对象的实例
  Object o = Class.forName("xxx").newInstance();

6、反射:数组       Arrays工具类用于完成对数组的反射操作, 
1、字节码对象比较的时候用== 号更精确
2、Arrays.asList(A)  类型转换
3、当A属于Objcet 类型数组时,可以转换并输出
4、当A不属于Object类型数组时,比如int 类型时,无法转换
7、反射:泛型
getActualTypeArguments()   返回表示此类型实际类型参数的 Type 对象的数组。
[0]就是这个数组中第一个了
  getOwnerType()  返回 Type 对象,表示此类型是其成员之一的类型。
  getRawType()  返回 Type 对象,表示声明此类型的类或接口。   
ParameterizedType获取java泛型参数类型
getGenericType  返回    泛型
-------------------------------------------------------
|-- java1.5新特性
|-- 高级for 循环
|-- 可变参数  (Varargs)
|-- 自动封装箱 autoboxing和unboxing
|-- 静态导入 (Static Imports)
|-- 享元模式 Flyweight
|-- 枚举(Enums)
|-- 泛型  Generic

|-- 枚举
|-- 反射
|-- javabean 和内省
|-- 注解
|-- 泛型
|-- 类加载器
|-- 代理类
-------------------------------------------------------
反射:
简单来说:
          就是能把任意Java类中的各种成份映射成相应的Java类(反射技术更像是对一个类进行解剖)
这个各种成份,就是指Java的组成部分
变量,构造方法,方法,修饰符,包等
Field、Constructor、Method
反射更像是动态加载,通过加载一个指定的类,获取该类中的所有的内容,并将字节码文件封装成对象,
这样便于操作这些成员,大大的增强了程序的扩展性。

反射的基本步骤: 
1、获得Class对象,就是获取到指定的名称的字节码文件对象。 
2、实例化对象,获得类的属性、方法或构造函数。 
3、访问属性、调用方法、调用构造函数创建对象。

得到类的字节码文件相同,这三种方式。
1.Class cls1=类名.class 相对简单,还是需要明确类名
2.clzz.getclass();必须要明确具体的类,并创建对象
3.class.forName("完整的类名(带包名)");
九大预定义Class对象:
8大基本数据类型对应的Class对象
void 对应的Class独享
参看:Class.isPrimitive()
int.class = Integer.TYPE;

数组
class.isArray();

总之:只要是源程序中出现的类型,都有自己的Class 字节码对象
例如int[] void.....
--
【1】
Constructor 构造方法反射技术
//【】反射技术:获取构造方法
	public static void getConstructor()throws Exception
	{
		//【个人应用】
				//  获取一个类的构造方法,成员变量,方法。
				
				Constructor[] constructors =person.classgetDeclaredConstructors();
				//打印出 该方法中的所有构造函数
				for(Constructor constructor : constructors){
					System.out.println(constructor); 
				}//高级for循环
				//知道有两个构造方法后,最有参方法进行传参
				//获取 有参方法对象
				Constructor con = person.class.getDeclaredConstructor(String.class);
				// 把 有参方法实例化,并传递一个参数  用同类型的对象进行接收
				person pp =(person)con.newInstance("xx");
				System.out.println(pp);
				
				//【老师案例】
				System.out.println("----------------");
				//new String(new StringBuffer("abc"));
						//得到构造方法 
				Constructor constructor = String.class.getConstructor(StringBuffer.class);
				//这里是选择	StringBuffer的构造方法
				System.out.println(constructor);
				//在用构造方法new一个		newInstance
				//String str2 =(String) constructor.newInstance("abc");
				//编译正确,运行报错IllegalArgumentException:  因为 constructor 
				//接收的是一个 StringBuffer 类型的构造函数,而传递的不是。所以错。
				String str2 =(String) constructor.newInstance(new StringBuffer("abc"));
				//而这里是 表示用这个构造方法的时候,还在传递一个StringBuffer 对象进去
				
				System.out.println(str2);
				System.out.println(str2.charAt(2));
	}
方法摘要
Constructor<?>[] getDeclaredConstructors()返回 Constructor 对象的一个数组,所有的包括:公共、保护、默认(包)访问和私有构造方法
getConstructor 返回指定构造方法
Annotation[] getDeclaredAnnotations() 返回直接存在于此元素上的所有注释。
Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,
这些对象表示此 Constructor 对象所表示构造方法的形参类型。 
newInstance 创建实例对象

---------------------------
【2】
Field 成员变量反射技术
//【】反射技术:获取变量
	public static void getField()throws Exception
	{
		Field[] fields1 = person.class.getDeclaredFields();
		//遍历打印出所有成员变量--以及类型
		for(Field field : fields1){			
			System.out.println(field.getType()+" "+field.getName());
		}
		person p = new person("oo",7);
		// 获取【公共】成员变量--并进行传参--打印
		Field field1 = p.getClass().getField("x");
		field1.set(p, "bbq");
		System.out.println(p);
		// 获取【私有】成员变量--并进行传参--打印
		//Field field2 = p.getClass().getField("y"); // 获取私有成员变量失败
		Field field2 = p.getClass().getDeclaredField("y");//  强制可读
		//field2.set(p, "mm-"); 给私有成员变量设值失败
		field2.setAccessible(true);//强制可写
		field2.set(p, "mm-");
		System.out.println(p);
		//getDeclaredField()--setAccessible()   传说中的暴力反射
		
		//对于该类中 默认修饰符的 int 类型 同样需要   暴力反射
		Field field3 = p.getClass().getDeclaredField("z");
		field3.setAccessible(true);//强制可写
		//对基本类型  可以直接进行 set类型
		
		// 把所有b替换为a。
		System.out.println("替换前:"+p);
		field3.setInt(p, 99);
		Field[] fields2=p.getClass().getFields();//获取全部对象 
			for(Field field :fields2){
			   //if(field.getType().equals(String.class)){ 
			    	//字节码 用 ==  号比较, 因为字节码只有一份
			   if(field.getType()==String.class){//如果是字符串
				   String oldValue = (String)field.get(p);//获取字符串内容
			       String newValue = oldValue.replace('b','a');//将字符串内容替换
			       field.set(p,newValue);//将新值赋给对象  
			   }     
			}
		 System.out.println("替换后:"+p);
	}
方法摘要
getDeclaredFields() 返回所有成员变量, 包括公共,私有
getField("y")       返回指定成员变量
暴力反射:
getDeclaredField("y");//  强制可读
field2.setAccessible(true);//强制可写
replace('b','a')  替换
getType()         返回类型
字节码对象进行比较 时用 == 号
---------------------------  
【3】
Method  方法的反射技术
私有方法 同私有变量都需要暴力反射才能使用
通过:设定setAccessible(true); 进行暴力反射
//【】反射技术:获取方法
	public static void getMethod()throws Exception
	{
		System.out.println("该类中所有方法:");
		Method[] methods = person.class.getDeclaredMethods();
		//遍历 打印
		for(Method method : methods){
			String s = method+"";
			s = s.substring(0,s.indexOf(' '));
			System.out.println(s+" "+method.getName());
		}
		
		Class c = Class.forName("Senior.person");
		Object o = c.newInstance();
		System.out.println("静态方法:");
		Method method1 = person.class.getMethod("show4", int.class);
		method1.invoke(null,999);//null 代表目标的静态方法
		System.out.println("空参数普通方法:");  
		Method method2 = person.class.getMethod("show3");
		method2.invoke(o);
		System.out.println("带参私有方法:");  
		Method method3 = person.class.getDeclaredMethod("show1",String.class);
		method3.setAccessible(true);
		String str = (String)method3.invoke(o,"暴力反射私有方法");
		System.out.println(str);
	}
//【反射技术,调用一个类的 mian方法】	

	// main 方法
	public static void main(String[] args) throws Exception
	{
		System.out.println("----------------Constructor----------------");
		//getConstructor();
		System.out.println("----------------   Field   ----------------");
		//getField();  
		System.out.println("----------------   Method  ----------------");
		//getMethod();
		System.out.println("反射技术,调用一个类的 mian方法:");
		String className = args[0];
		showMain(className);
	}		
	//【】反射技术:调用某个类的Main 方法
	private static void showMain(String className)
			throws NoSuchMethodException, ClassNotFoundException,
			IllegalAccessException, InvocationTargetException {
			//获取className 指向的类 的  Main 方法
		Method mt = Class.forName(className).getMethod("main",String[].class);
			
		//mt.invoke(null, (Object)new String[]{"321","rete","54353"});
			//invoke调用(静态方法,传递一个Object 数组)
		mt.invoke(null, new Object[]{new String[]{"321","rete","54353"}});
	}	
	//被调用的类
class showMainMethod{
	public static void main(String[] args) {
		for(String arg : args){
			System.out.println(arg);
		}
		
	}
}
方法摘要
getDeclaredMethods 返回所有方法
Class.forName("xxx");  返回xxx 的字节码对象
invoke(null,999)  invoke发送指令调用目标方法    null  代表 静态方法


反射技术,调用一个类的 mian方法时注意:
1、在控制台
首先 javac Test.java
然后 java Test  showMainMethod.java


2、在myeclipse 
  设定 Run As>>Run Config>>Arguments>> program arguments 
  为 com.itheima.day2.CaoNimaAA(类带上包名)

【4】
反射技术:数组
只要是源程序中出现的类型,都有自己的Class 字节码对象
那么数组也应该有自己的Class对象
通过 ReflextArray1和2 可以看出,
1、具有相同类型的数组   他们的Class字节码 相同
2、说明Class 字节码的唯一性,(字节码对象的比较用== 好更精确)
3、他们的父类都是Object
4、Arrays.asList方法下,八大基本类型-- 无法转型
printObject 为 反射方法。
//【】反射技术:数组的反射
	private static void ReflextArray1() {
		//int []    a1 = new int [3];
		int []    a2 = new int [4];
		int [][]  a3 = new int [3][4];
		//String [] a4 = new String[3];		
		int []    a1 = new int []{2,3,1,7};
		String [] a4 = new String[]{"q","d","g"};		
		System.out.println(a1.getClass() == a2.getClass());//类型相同 都是 数组 Int 类型
		System.out.println(a1.getClass().getName() == a3.getClass().getName());//数组的数组, 不同
		System.out.println(a1.getClass().getName() == a4.getClass().getName());//类型不同
		//System.out.println(a2.getClass()+"。。。。。"+a2.getClass().getName());		
		System.out.println("----:发现他们的父类都是 Object:");
		System.out.println(a2.getClass().getSuperclass().getName());
		System.out.println(a3.getClass().getSuperclass().getName());
		System.out.println(a4.getClass().getSuperclass().getName());  		
		System.out.println("----");		
		ReflextArray2(a3, a1, a4);
	}
	private static void ReflextArray2(int[][] a3, int[] a1, String[] a4) {
		Object obj0 = a1;
		Object obj1 = a3;
		Object obj2 = a4;	
			//	Integer [] in = new Integer[1];
			//	Object[] obj3 = in;
		//Object[] obj3 = a1;// 基本类型不是Objcet 类型,所以报错,Integer 才是
		Object[] obj4 = a3;//表示 a3 是一个数组,数组中装的是数组。
		Object[] obj5 = a4;
		System.out.println("----打印查看数组内容:");	
		System.out.println(a1);	
		System.out.println(a4);			
		System.out.println(<Arrays.asList(a1));	//int 类型没有转换
		System.out.println(Arrays.asList(a4));  //String 类型成功转换
		System.out.println("----证明:八大类型因为不是Objcet类型,所以 :Arrays.asList 无法转型。");	
		long [] l = {321312};
		double [] d = {2.1,32.1};
		System.out.println(Arrays.asList(l));//long 类型没有转换
		System.out.println(Arrays.asList(d));//double 类型没有转换
		System.out.println("----");			
		printObject(a4); //String 类型成功转换
		printObject("dsfsd");//String 类型成功转换
	}
	//【】反射技术:数组转型
	private static void printObject(Object  obj) {
		//获取目标对象的Class字节码对象
		Class cl =obj.getClass();
		//进行转型
		if(cl.isArray()){
			//获取该目标数组长度
			int len = Array.getLength(obj);
			//遍历目标数组元素
			for(int i = 0 ;i<len ; i ++){
				System.out.println(Array.get(obj,i));
			}
		}else{
			System.out.println(obj);
		}
	}
方法摘要
Arrays.asList(l)  类型转换
getType()  返回类型
get()    返回字段
【5】
反射技术:泛型
//【】反射技术:泛型的反射
public class GetGenericType {
	// 有 泛型的   双列集合 变量
	Map<String,Integer> map = new HashMap<String,Integer>();
	
	public static void main(String[] args) throws Exception {
		// 获取 GetGenericTypeDemo14 类的字节码对象
		Class c = GetGenericType.class;
		//获取变量 map 
		Field f = c.getDeclaredField("map");
		System.out.println(f);
		System.out.println("变量名:"+f.getName());
		
		// Class<?> getType()返回该变量的声明类型。 
		Class cl = f.getType();
		System.out.println("获得其类型:"+cl);
		//获得其类型:interface java.util.Map
		
		 //Type getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。 
		 //【】Type是Class的接口;
		Type t = f.getGenericType();//包含泛型的类型
		System.out.println(t+"\n\t\t>>>[GenericType]");
		//打印:java.util.Map<java.lang.String, java.lang.Integer>
		//Type这个类里面没有任何的方法,所以需要调用子类的方法,那么大的类型转到小的类型,需要强转!
		ParameterizedType pt = (ParameterizedType)t;//强转到其子类 
		
		t = pt.getRawType();//类型的类或接口
		System.out.println(t+"|>");
		
		Type[] ts = pt.getActualTypeArguments();
		for (Type type : ts) {
			System.out.println(type);
		}	
	}
}
方法摘要
 Type[] getActualTypeArguments()   返回表示此类型实际类型参数的 Type 对象的数组。[0]就是这个数组中第一个了
 Type getOwnerType()  返回 Type 对象,表示此类型是其成员之一的类型。
 Type getRawType()  返回 Type 对象,表示声明此类型的类或接口。   
        ParameterizedType获取java泛型参数类型
        getGenericType  返回    泛型







---------------------------------------------------------------------------------------------------------------------------------------------
---------- android培训、 java培训、期待与您交流!----------


----------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值