反射知识梳理
---------------------------------------------------------------------------------------------------------------------------------------------
1、反射: 简单说就把Java类中的各种成份映射成相应的Java类
2、方法摘要:
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 构造方法反射技术
【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培训、期待与您交流!----------
----------------------------------------------