黑马程序员──反射

来源:互联网 发布:开淘宝网店怎么弄客服 编辑:程序博客网 时间:2024/06/06 03:30

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


反射


反射的用法:先获取字节码,字节码调用Class类中的方法(比如getMethod),获取到对应的类(Method)的实例对象(show());
此实例对象(show())就可以调用类(Method)中的方法,比如invoke(Object  obj  , 参数),这样就达到了反射的目的。


得到Class 实例对象 -字节码的三种方式

类名.class
对象.getClass()
Class.forName("完整类名字符串")

对于同一个类,字节码只存在一份。

<span style="font-size:12px;">public class GetClass {public static void main(String[] args) throws ClassNotFoundException {String s = "abc";Class cls1 = s.getClass();Class cls2 = String.class;Class cls3 = Class.forName("java.lang.String");//System.out.println(cls1==cls2);//System.out.println(cls2==cls3);Class cls4 = int.class;Class cls5 = Integer.class;//System.out.println(cls4==cls5);Class cls6 = void.class;//System.out.println(cls5.isPrimitive());System.out.println(boolean.class==Boolean.TYPE);}}</span>

九个基本数据类型的字节码
int.class     boolean.class     void.class .....
反射就是将java类中的各个成分映射成对应的Java类

构造方法--> getConstructor(Class<?>... parameterTypes)

示例:
<span style="color:#330033;">public class ConstructorDemo {public static void main(String[] args)throws Exception {//new String("abc"); Constructor cons = String.class.getConstructor(String.class); String str = (String)cons.newInstance("abc");  System.out.println(str); }}</span>

当需要获取的构造方法是无参数时:我们可以这样做 Class.newInstance( ).

成员变量--> getField(String name)

Field 代表的是字节码中的变量,不是具体对象上的变量。

变量必须是public修饰才行。

如果是默认权限(不能看见,可以访问),需要用getDeclaredField("name")来关联此字段,然后就可以get方法获取。

如果是private修饰(不能看见,不能访问)-->暴力反射!

public static void main(String[] args)throws Exception {ReflctPerson rp = new ReflctPerson(5,"haha");Field field =  rp.getClass().getField("age");int age = (int)field.get(rp);//System.out.println(age);ReflctPerson rp1 = new ReflctPerson();Field field2 =  rp1.getClass().getDeclaredField("name");field2.setAccessible(true);  //对private属性强行访问,这就是暴力反射!String name = (String)field2.get(rp1);System.out.println(name);

练习:将一个对象中所有String类型的变量中的'b'变成'a'。

注意:Field有getType()方法,获取变量的声明类型。而且字节码比较用== 比较专业。

public static void main(String[] args)throws Exception {PersonString ps = new PersonString();System.out.println(ps);Field[] fields = ps.getClass().getFields();//获取所有字段for(Field field : fields)//高级for循环{if(field.getType()==String.class)//判断类型{String str = (String)field.get(ps);//获取变量//System.out.println(str);str = str.replace('b','a');//替换//System.out.println(str);field.set(ps, str);//设置变量}}System.out.println(ps);}

成员函数-->getMethod(String name, Class<?>... parameterTypes)

invoke(Object obj, Object... args)  

如果invoke(null,object   args)那么,这个方法是静态的!!!

invoke(null,new  Object[]   args) 1.4语法    会将数组拆开,里面的元素才是参数。

示例:

public static void main(String[] args)throws Exception {String s = "abc";Method me = s.getClass().getMethod("charAt", int.class);System.out.println(me.invoke(s, 2));}


MainReflctTest     用反射调用输入类名的main方法。 注意invoke(null,new  Object[]   args) 1.4语法    会将数组拆开,里面

的元素才是参数。可以通过外包Object[]或者(Object)声明是对象,不进行拆包。

public static void main(String[] args)throws Exception {String className = args[0];Method mainMethod = Class.forName(className).getMethod("main", String[].class);//mainMethod.invoke(null, new Object[]{new String[]{"aaa","bbb","ccc","wanan"}});mainMethod.invoke(null, (Object)new String[]{"aaa","bbb","ccc","wanan"});


数组:

具有相同维数和元素类型的数组属于同一类型,即具有相同的Class实例对象。

代表数组的Class实例对象的getSuperclass( )方法返回父类为Object类对应的Class。

基本数据类型数组比如  int[]  是被当做一个Object,
对于非基本数据类型数组 比如 String[] 当做 Object[].

数组存入集合:Arrays.asList().
int [] a1 = new int [] {1,2,3},把整个数组作为集合的一个元素。不符合1.4的语法,所以用1.5语法。
String [] a4 = new String [] {"a","b","c"},数组中的每一个元素作为集合中的元素。

Array 类   java.lang.reflect.Array
static Objectget(Object array, int index) static intgetLength(Object array)示例:通过反射遍历数组
private static  void print(Object obj) {Class las = obj.getClass();if(las.isArray())//判断类型{int leng = Array.getLength(obj);//获取数组长度for(int i=0;i<leng;i++){System.out.println(Array.get(obj, i));//获取数组元素}

反射的作用-->实现框架功能

写框架的时候不知道要调用的类名,我们不能直接new对象,需要通过Class.forName()来操作,这就是反射的作用。

练习:对集合进行反射操作

类加载器加载文件 ClassLoader

InputStream fis = ColletionReflct.class.getResourceAsStream("My.properties");Properties pro = new Properties();pro.load(fis);fis.close();String className = (String)pro.get("className");Collection con = (Collection)Class.forName(className).newInstance();con.add("aaa");con.add("aaa");System.out.println(con.size());
JavaBean介绍

JavaBean是一种特殊的Java类,主要用于传递数据信息。这种Java类中的方法主要用于访问私有的字段。而且方法名命名符合某种规则。

规则就是setXxx和getXxx。

通过JavaBean的方式来获取私有属性。

PropertyDescriptor类 和对应的Read和Write方法

public static void main(String[] args)throws Exception {ReflctPerson rp = new ReflctPerson();String propertyName = "name";PropertyDescriptor pd = new PropertyDescriptor(propertyName,rp.getClass());Method get = pd.getReadMethod();//获取get方法。Object retVal = get.invoke(rp);System.out.println(retVal);Method set = pd.getWriteMethod();//获取set方法。set.invoke(rp,"haha");System.out.println(rp.getName());

以上内容为本人笔记,仅供参考。






































0 0
原创粉丝点击