反射机制
来源:互联网 发布:no sleep for mac下载 编辑:程序博客网 时间:2024/05/17 02:29
反射机制
反射的基本概念
反射就是把Java类中的各种成分映射成相应的java类.
Class类
表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象
字节码 :
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示
三种获得字节码的方式:
类名.class();
对象.getClass();
Class.forName(“类名”);
String str = "asd";//输出结果为class java.lang.StringSystem.out.println(String.class);System.out.println(str.getClass());System.out.println(Class.forName("java.lang.String"));
九个预定义Class实例对象:
分别为:char,short,byte,int,long,float,double,boolean和void.
Class.isPrimitive可以检查是否为基本类型
Int.class ==Integer.TYPE
Class.isArray()
System.out.println(int.class); //intSystem.out.println(int.class.isPrimitive()); //trueSystem.out.println(int.class == Integer.TYPE); //true<span lang="EN-US"></span>
Constructor类
Constructor类代表某个类中的一个构造方法
根据构造方法的参数的个数和类型,来获取不同的构造方法.方法的各个参数的类型用Class对象表示
//得到某个类中所有构造方法Constructor[] con = Class.forName("java.lang.String").getConstructors();//获得某个类并创建Constructor constructor = String.class.getConstructor(StringBuffer.class);String str1 = (String)constructor.newInstance(new StringBuffer("itheima"));System.out.println(str1);
可以利用泛型提前确定数据类型省去强制类型转换
Constructor<String> constructor2 = String.class.getConstructor(StringBuffer.class);String str2 = constructor2.newInstance(new StringBuffer("itheima"));
Class类提供货了newInstance()方法用于直接构造没有参数的类
String.class.newInstance();
Field类
Field类代表某个类中的一个成员变量
public static void main(String[] args) throws Exception{Point p = new Point(1,4);//获得public属性的值Field fieldY = p.getClass().getField("y");//类中的非静态的属性需要一个对象来取出这个对象中的值System.out.println(fieldY.get(p)); //获取private属性的值//私有属性不能使用getField()方法Field fieldX = p.getClass().getDeclaredField("x");//获得私有属性后,需强制破解才能获得或修改值fieldX.setAccessible(true);fieldX.set(p, 12);//获得类的静态属性Field fieldZ = p.getClass().getField("z");System.out.println(fieldZ.get(Point.class));}}class Point {private int x;public int y;public static int z = 0;public Point(int x, int y) {super();this.x = x;this.y = y;}}
作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"
package com.itheima.reflect;import java.lang.reflect.Field;public class replaceChar {public static void main(String[] args) {TestClass test = new TestClass();System.out.println("替换前" + test);replaceCharB(test);System.out.println("替换后" + test);}private static void replaceCharB(Object obj) {Field[] fields = obj.getClass().getFields();for(Field field : fields) { if(field.getType() == String.class) { //检测是否为String String str = null;try {str = (String)field.get(obj); } catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}String newStr = str.replace('b', 'a'); //replace方法不会改变str的原值try {field.set(obj, newStr); //将str重新设置回去} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}class TestClass {public String str1 = "bbbbbbbbbbbbb";public String str2 = "babfbdsbd";public String str3 = "ball";public int i = 0;@Overridepublic String toString() {return "TestClass [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3+ ", i=" + i + "]";}}
Method
Method类代表某个类中的一个成员方法
String str = "abc";//调用String类的chatAt(int) 方法Method stringCharAt = String.class.getMethod("charAt", int.class);System.out.println(stringCharAt.invoke(str, 1));当Method.invoke(null, )方法的第一个参数为null时,代表该Method方法为静态方法.
main方法的反射:
mian方法传递String数组数据的两个解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"});,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了
Method reflectMainMethod = Class.forName(args[0]).getMethod("main", String[].class);reflectMainMethod.invoke(null, (Object)new String[]{"111", "222", "333"});reflectMainMethod.invoke(null, new Object[]{new String[]{"111", "222", "333"}});
数组的反射
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;
非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
public static void main(String[] args) {int[] a1 = new int[3];int[] a2 = new int[4];int[][] a3 = new int[1][3];String[] a4 = new String[1];a4[0] = "sdfs";System.out.println(a1.getClass() == a2.getClass());System.out.println(a1.getClass() == (Object)a3.getClass());System.out.println((Object)a1.getClass() == a4.getClass());//不加强制转换会直接报错 不知道为什么 强制转换加到哪是一样的System.out.println(a1.getClass().getName());System.out.println(a3.getClass().getSuperclass().getName());Object o1 = a1;Object o2= a4;//Object[] o3 = a1;Object[] o4 = a3;Object[] o5 = a4;//Arrays类System.out.println(Arrays.asList(a3));Object obj;printObject(a1);}
//利用数组的反射输出数据private static void printObject(Object obj) {Class claszz = obj.getClass();if(claszz.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);}}
简单框架实例
框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {//根据配置文件来调用配置文件中的Collection的子类String objectClass;FileInputStream fis = new FileInputStream("ReflectClass.Properties");Properties pro = new Properties();pro.load(fis);fis.close();objectClass = pro.getProperty("objectClass");Class cla = Class.forName(objectClass);Collection collection = (Collection)cla.newInstance();}
配置文件的位置
配置文件应尽量写绝对路径,最好在使用时专门设置一个放配置文件的目录
类名.Class.getClassLoader.getResourceAsStream(String name)
可以指定当前包下的文件
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- 反射机制
- SQL中随机数函数rand()
- 委托
- Climbing Stairs -- LeetCode
- 修改myeclipse的主题背景
- 细节的力量
- 反射机制
- 广告
- 会遇到的问题
- MyEclipse优化方案
- android之startService和bindService方法的区别
- cocos2d-x 3.0的坑有哪些
- 第7周作业1-循环大战
- Create environment for DVWA on Windows7
- java数组