Java反射之method,数组与Object关系,泛型参数
2014-08-21 00:39
274 查看
1.反射的基石-->Class
1.1.Class类
一个类被类加载器加载到内存中,占用一片存储区域,这个空间里面的内容就是类的 字节码 .
不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示;
显然可以为这些组织字节码内容的类定义一个类型,它就是Class类型
1.2.如何得到各字节码对应的Class类实例对象
三种方式:
(1)Class cls1=类名.class 相对简单,还是需要明确类名:System.class;
(2)Class cls1=对象.getClass();必须要明确具体的类,并创建对象:new Date().getClass();
(3)Class cls1=Class.forName("完整的类名(带包名)"):Class.forName("java.util.Date")
1.3.九个预定一个Class实例对象
八个基本类型+void.Class
Integer.class包装类的字节码
只要在源程序中出现的类型,都有各自的Class实例对,例如 int[],void 等等;
2.反射
就是把JAVA类中的各种成分反射成为相应的JAVA类
反射的好处: 大大的增强了程序的扩展性.
3.反射的基本步骤:
(1)获得Class对象,就是获取到指定的名称的字节码文件对象.
(2)实例化对象,获得类的属性/方法或构造函数.
(3)访问属性、调用方法、调用构造函数创建对象.
4.构造方法的反射应用
4.1.得到某个类中所有的构造方法
Constructor constructors[]= Class.forName("").getConstructors();;
4.2.得到某一个具体的构造方法:用参数定义
Constructor constructor= Class.forName("").getConstructor(StringBuffer.class);
4.3.用反射构建类的实例:中转作用
(1)class-->constructor-->new object:带参数的Constructor的newInstance()
String name="com.dsa.类名";
得到某一个指定构造方法
onstructor constructor= Class.forName("").getConstructor(String.class);
创建实例对象
Object obj=constructor.newInstance("abc");
通过构造方法的反射来new String(new StringBuffer("abc")):newInstance();
/*详细说明:
//用getConstructor来获取构造方法,用StringBuffer.class反射的SB类定义了构造方法的参数类型,
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
//使用Constructor的newInstance创建实例,注意构造参数对象参数保持之前定义的类型;
//编译期不知道反射过来的对象是String,要加上该类句柄;
String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));*/
(2)class-->new object
如果构造方法不带参数,可以直接用Class.newInstance();
String name="com.dsa.类名";
寻找该名称类文件,并加载进内存,并非产生Class对象
Class cls=Class.forName(name);
用Class的newInstance()产生该类的对象
Object obj=cls.newInstance();
5.成员变量 Filed类的反射: 代表某个类中的一个成员变量
ReflectPoint pt1=new ReflectPoint(3,5);
Field fieldY=pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));//get()获得具体对象中的值
Field fieldX=pt1.getClass().getDeclaredField("x");//获得变量不管私有或保护;
fieldX.setAccessible(true);//暴力反射!
System.out.println(fieldX.get(pt1));
成员变量的综合应用:
changeStringValue(pt1);
System.out.println(pt1);
6.成员方法的反射 Method
反射形式:
(1)获取Method字节码:Class.getMethod("方法名",参数字节码)//参数字节码可为空null
(2)反射取方法:invoke(对象名,参数)//对象名为null表示静态方法
6.1.String类的charAt()方法示例:
Method methodCharAt = String.class.getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str1,1));
System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//jdk1.4
6.2.对接收数组参数的成员方法进行反射:main方法演示
String startingClassName= args[0];//在run对话框中植入TestArguments给args[0]
Method mainMethod= Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
7.数组与Object的关系及其反射类型
Arrays.asList(int[])和String[]的差异:因为兼容jdk1.4,String可以上溯Object的关系.
Object aObj1=a1;
Object aObj2=a4;
//Object[]aObj3=a1;//一维数组不能转为Object;
Object aObj4=a3;
Object aObj5=a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//int类集合不能打出
System.out.println(Arrays.asList(a4));//String集合可以直接打出
8.数组的反射应用:当Class isArray()
示例:(对比Field的应用)
9.通过反射获得泛型的实际类型参数
9.1.通过指定对应的Class对象,程序可以获得该类里面所有的Field,获得Field对象f后都可以使用getType()来获取其类型.
Class<?> type = f.getType();//获得字段的类型
但此方法只对普通Field有效,若该Field有泛型修饰,则不能准确得到该Field的泛型参数,如Map<String,Integer>;
反射获得指定Field的泛型类型步骤:
(1)获取当前Class类-->泛型类Field;
(2)用getGenericType(),得到泛型类型:
Type gType = f.getGenericType();
(3)将Type对象强转为子类ParameterizedType:
(4)使用getRawType()获得泛型类型,使用getActualTypeArguments()获得参数类型;
Type getRawType()//返回被泛型限制的类型;
Type[] getActualTypeArguments()//返回泛型参数类型;
示例:
1.1.Class类
一个类被类加载器加载到内存中,占用一片存储区域,这个空间里面的内容就是类的 字节码 .
不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示;
显然可以为这些组织字节码内容的类定义一个类型,它就是Class类型
1.2.如何得到各字节码对应的Class类实例对象
三种方式:
(1)Class cls1=类名.class 相对简单,还是需要明确类名:System.class;
(2)Class cls1=对象.getClass();必须要明确具体的类,并创建对象:new Date().getClass();
(3)Class cls1=Class.forName("完整的类名(带包名)"):Class.forName("java.util.Date")
1.3.九个预定一个Class实例对象
八个基本类型+void.Class
Integer.class包装类的字节码
public static void main(String[] args) throws Exception { // TODO Auto-generated method stub String str1 = "abc"; Class cls1 = str1.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); System.out.println(cls1==cls2); System.out.println(cls1==cls3); System.out.println(cls1.isPrimitive());//是否基本类型,String不是基本类型 System.out.println(int.class.isPrimitive());//true System.out.println(int.class==Integer.class);//false,Integer.class是包装类的字节码 System.out.println(int.class==Integer.TYPE);//true,Integer.TYPE是其基本类型的字节码 //数组类型的Class类型实例对象Class.isArray System.out.println(int[].class.isPrimitive());//false System.out.println(int[].class.isArray());//true }
只要在源程序中出现的类型,都有各自的Class实例对,例如 int[],void 等等;
2.反射
就是把JAVA类中的各种成分反射成为相应的JAVA类
反射的好处: 大大的增强了程序的扩展性.
3.反射的基本步骤:
(1)获得Class对象,就是获取到指定的名称的字节码文件对象.
(2)实例化对象,获得类的属性/方法或构造函数.
(3)访问属性、调用方法、调用构造函数创建对象.
4.构造方法的反射应用
4.1.得到某个类中所有的构造方法
Constructor constructors[]= Class.forName("").getConstructors();;
4.2.得到某一个具体的构造方法:用参数定义
Constructor constructor= Class.forName("").getConstructor(StringBuffer.class);
4.3.用反射构建类的实例:中转作用
(1)class-->constructor-->new object:带参数的Constructor的newInstance()
String name="com.dsa.类名";
得到某一个指定构造方法
onstructor constructor= Class.forName("").getConstructor(String.class);
创建实例对象
Object obj=constructor.newInstance("abc");
通过构造方法的反射来new String(new StringBuffer("abc")):newInstance();
/*详细说明:
//用getConstructor来获取构造方法,用StringBuffer.class反射的SB类定义了构造方法的参数类型,
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
//使用Constructor的newInstance创建实例,注意构造参数对象参数保持之前定义的类型;
//编译期不知道反射过来的对象是String,要加上该类句柄;
String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));*/
(2)class-->new object
如果构造方法不带参数,可以直接用Class.newInstance();
String name="com.dsa.类名";
寻找该名称类文件,并加载进内存,并非产生Class对象
Class cls=Class.forName(name);
用Class的newInstance()产生该类的对象
Object obj=cls.newInstance();
5.成员变量 Filed类的反射: 代表某个类中的一个成员变量
ReflectPoint pt1=new ReflectPoint(3,5);
Field fieldY=pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));//get()获得具体对象中的值
Field fieldX=pt1.getClass().getDeclaredField("x");//获得变量不管私有或保护;
fieldX.setAccessible(true);//暴力反射!
System.out.println(fieldX.get(pt1));
成员变量的综合应用:
changeStringValue(pt1);
System.out.println(pt1);
private static void changeStringValue(Object obj) throws Exception { Field[] fields=obj.getClass().getFields();//获得obj的所有变量 for(Field field: fields){ // if(field.getType().equals(String.class))//都是字节码用==; if(field.getType()== String.class){ String oldValue = (String)field.get(obj); String newValue = oldValue.replace('b', 'a');//用a替换b; field.set(obj, newValue);//两个对象交换; } } }
6.成员方法的反射 Method
反射形式:
(1)获取Method字节码:Class.getMethod("方法名",参数字节码)//参数字节码可为空null
(2)反射取方法:invoke(对象名,参数)//对象名为null表示静态方法
6.1.String类的charAt()方法示例:
Method methodCharAt = String.class.getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str1,1));
System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//jdk1.4
6.2.对接收数组参数的成员方法进行反射:main方法演示
String startingClassName= args[0];//在run对话框中植入TestArguments给args[0]
Method mainMethod= Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
class TestArguments{ public static void main(String[] args){ for(String arg: args){ System.out.println(arg); } } }
7.数组与Object的关系及其反射类型
Arrays.asList(int[])和String[]的差异:因为兼容jdk1.4,String可以上溯Object的关系.
Object aObj1=a1;
Object aObj2=a4;
//Object[]aObj3=a1;//一维数组不能转为Object;
Object aObj4=a3;
Object aObj5=a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//int类集合不能打出
System.out.println(Arrays.asList(a4));//String集合可以直接打出
8.数组的反射应用:当Class isArray()
示例:(对比Field的应用)
private static void printObject(Object obj) { Class clazz=obj.getClass(); if(clazz.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); } }
9.通过反射获得泛型的实际类型参数
9.1.通过指定对应的Class对象,程序可以获得该类里面所有的Field,获得Field对象f后都可以使用getType()来获取其类型.
Class<?> type = f.getType();//获得字段的类型
但此方法只对普通Field有效,若该Field有泛型修饰,则不能准确得到该Field的泛型参数,如Map<String,Integer>;
反射获得指定Field的泛型类型步骤:
(1)获取当前Class类-->泛型类Field;
(2)用getGenericType(),得到泛型类型:
Type gType = f.getGenericType();
(3)将Type对象强转为子类ParameterizedType:
(4)使用getRawType()获得泛型类型,使用getActualTypeArguments()获得参数类型;
Type getRawType()//返回被泛型限制的类型;
Type[] getActualTypeArguments()//返回泛型参数类型;
示例:
import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; publ 4000 ic class GetGenericTypeDemo { Map<String,Integer> map = new HashMap<String,Integer>(); public static void main(String[] args) throws Exception { Class c = GetGenericTypeDemo.class; //原Field反射方式获得泛型类型 Field f = c.getDeclaredField("map"); System.out.println(f); System.out.println(f.getName());//map /* // 返回一个 Class 对象 Class cl = f.getType(); //获得其类型:interface java.util.Map System.out.println("获得其类型:"+cl);*/ //包含泛型的类型 Type t = f.getGenericType(); System.out.println(t);//java.util.Map<java.lang.String, java.lang.Integer> //Type这个类里面没有任何的方法,所以需要调用子类的方法 ParameterizedType pt = (ParameterizedType)t; t = pt.getRawType();//类型的类或接口 System.out.println(t); //获取泛型元素class java.lang.String,class java.lang.Integer Type[] ts = pt.getActualTypeArguments(); for (Type type : ts) { System.out.println(type); } } }
相关文章推荐
- 23对接收数组参数的成员方法进行反射24 数组与Object的关系及其反射类型25 数组的反射应用
- java反射之对象数组参数
- Java学习笔记003——继承、抽象类、类相等测试、泛型数组列表、可变参数方法
- Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用
- 【Java】JDK1.5以后新型的泛型参数传递方法Object...args
- 使用JAVA的反射机制反射带有数组参数的私有方法
- 01-java基础加强,eclipse工具使用,快捷键,断点调试,单元测试,jdk5新特性,增强for循环,集合map,list,可变参数,枚举,反射,泛型
- java基础-反射 --通过反射 获取泛型实际类型参数
- Java 泛型学习(三)通过反射获得泛型的实际类型参数
- java增强之泛型练习2:泛型DAO、通过反射获取泛型参数
- Java反射,参数为数组
- 数组与Object的关系及其反射类型
- java的反射机制(含数组参数)
- java 通过反射获得泛型的实际类型参数
- 神奇的java Object ( Object和数组关系) Object数据互转
- 加强eclipse的使用技巧。可变参数。基本数据类型自动装箱和拆箱。枚举。反射。数组反射的应用。ArrayList和HashSet。JavaBean
- 黑马程序员--Java基础加强--04.代码简化 书写规律III_数组参数【重载】【数组】【可变参数数组】【泛型可变参数数组】【个人总结】
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- 数组与Object的关系及其反射类型
- Java - 基础增强 - 增强for - 可变参数 - 枚举 - 反射 - 内省 - 泛型