黑马程序员——java高新技术--反射

来源:互联网 发布:淘宝7.1.0版本官方网 编辑:程序博客网 时间:2024/04/28 02:04

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

反射

1、Class2、反射 3、Constructor 4、Filed 5、Method

6、调用主函数7、数组 8、文件加载 9、集合 11、内省



反射

1、Class
Java中的所有类属于同一事物,描述该事物的类就是Class。Class反射的基石.

Class创建的实例是内存中字节码。字节码就是我们平常所说的类。

获得字节码有三种方式:

Person.class
new Person().getClass()
Class.forName("")

String s="abc";//获得字节码有三种方式Class s1=s.getClass();//从内存中获得Class s2=String.class;//知道类名去加载class文件,然后从内存中获得Class s3=Class.forName("java.lang.String");//不知道类名,传一个类名,然后去加载class文件,然后从内存中获得System.out.println(s1==s2);System.out.println(s2==s3);//三种方式获得为同一字节码System.out.println(String.class.isPrimitive());System.out.println(int.class.isPrimitive());System.out.println(int[].class.isArray());System.out.println(Integer.TYPE);//基本类型的TYPE字段
2、反射

反射就是把java类中的各种成分映射成java类。

java类中的成分,对应的类有:Field,Method,Contructor,Package...

3、Constructor

类代表某个类中的一个构造方法。获得的方式,一个类中很多个构造方法,怎么获得自己想要的那一个呢?

用参数类型来区分。

构造方法的获得比较耗性能,反射会引起性能下降。

//用反射实现new String(new StringBuffer("abc"));Constructor constructor1=String.class.getConstructor(StringBuffer.class);//得到String的一个构造函数,有一个参数,类型为StringBufferString ss=(String)constructor1.newInstance(new StringBuffer("abc"));System.out.println(ss.charAt(1));

4、Filed

表示类中字段这类事物。通过getField方法获得类中的成员,然后获得具体对象中的值。权限不同,获取成员及成员在对象上的值的操作不同。举例如下:

public class ReflectPoint {public int x;private int y;public ReflectPoint(int x, int y) {this.x = x;this.y = y;}}

非私有成员:

//获得rp对象上的x值ReflectPoint rp=new ReflectPoint(3,5);Field fx=ReflectPoint.class.getField("x");//返回的是成员System.out.println(fx.get(rp));
私有成员:

//获得rp对象上的y值Field fy=ReflectPoint.class.getDeclaredField("y");//只要你声明了 ,我就能拿到fy.setAccessible(true);//暴力反射,强制访问System.out.println(fy.get(rp));
练习:
<span style="white-space:pre"></span>// 一个修改字符串的小程序// 将字符值中得b修改为apublic static void changeStrigValue(Object object) throws Exception {Field[] fields = object.getClass().getFields();for (Field field : fields) {if (field.getType() == String.class) {String oldValue = (String) field.get(object);String newValue = oldValue.replace('b', 'a');field.set(object, newValue);// System.out.println(newValue);}}System.out.println(object);}

5、Method

//s.charAt(0);Method methodcharAt=String.class.getMethod("charAt", int.class);System.out.println(methodcharAt.invoke(s, 0));
System.out.println(methodcharAt.invoke(s, new Object[]{0}));

6、调用主函数

//TestArgs.main(new String[]{"111","222","333"});String startClassName=args[0];Method mainMethod=Class.forName(startClassName).getMethod("main", String[].class);mainMethod.invoke(null, (Object)new String[]{"111","222","333"});mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
class TestArgs{<span style="white-space:pre"></span>public static void main(String[] args){<span style="white-space:pre"></span>for(String s:args)<span style="white-space:pre"></span>System.out.println(s);<span style="white-space:pre"></span>}}
7、数组

//数组的反射public static void  arrayReflet(Object obj){Class clazz=obj.getClass();//反射的前提是得到字节码,根据字节码进行相关的操作if(clazz.isArray()){int length=Array.getLength(obj);for(int i=0;i<length;i++){System.out.println(Array.get(obj, i));}}else{System.out.println("obj");}}

8、文件加载

A.从PC加载

不是用硬编码,而是生成的目录(用户配置的选择)+在项目中得位置:FileInputStream("相对 :因为无法得知用户的选择,故只是相对用户选择的一个路径")

B.从classPath加载

(1):用类加载器:*.class.getLoader().getResourcesAs("classPath下的绝对路径");

(2):用类直接加载:*.class.getLoader().getResourcesAs("classPath下的绝对路径");

(3):用类直接加载:*.class.getLoader().getResourcesAs("classPath下的绝对路径");

public class ReflectTest {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stub/*getRealPath();//金山词霸/内部一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。*///InputStream ips = new FileInputStream("config.properties");//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");//InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties");InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");Properties props = new Properties();props.load(ips);ips.close();String className = props.getProperty("className");Collection collections = (Collection)Class.forName(className).newInstance();//Collection collections = new HashSet();ReflectPoint pt1 = new ReflectPoint(3,3);ReflectPoint pt2 = new ReflectPoint(5,5);ReflectPoint pt3 = new ReflectPoint(3,3);collections.add(pt1);collections.add(pt2);collections.add(pt3);collections.add(pt1);//pt1.y = 7;//collections.remove(pt1);System.out.println(collections.size());}}

9、集合

Hashcode()的作用:
修改Hash值
对象默认的Hash值,与对象在内存中的地址有关,Hash值是为了Hash集合检索方便,使用Hash算法,把Hash集合内部分成若干区域,每个区域的给一个Hash值与对象的Hash值对应;
所以,只有使用Hash集合它才有价值;
所以,要使两个对象在Hash集合中的引用是同一个,就的用Hashcode()方法修改Hash值;
注意:已存入Hash集合的对象,不能再修改Hash值有关的字段值,会引起内存泄露。

String className = (String) props.getProperty("className");Collection collection = (Collection) Class.forName(className).newInstance();// Collection collection=new HashSet();collection.add(pt1);collection.add(pt2);collection.add(pt3);collection.add(pt4);// pt1.x=6;// collection.remove(pt1);System.out.println(collection.size());

10、内省

intorspection内省,用来操作javaBean。
编写Person的javaBean:

public class Person(){public int age;public int getAge(){return age;}public void setAge(int age){this.age=age;}获取javaBean属性的方法:如果第二个字母是小写,则把set&get后第一个字母变成小写;如果第二个字母是大写,则把保持大写;eg: settime-->time(??)setTime-->timesetTIME-->TIME}//主要用到PropertyDescriptor,来操作javaBean的set&get方法private static void setObject(Object rp, String propertyName, Object object)throws Exception {PropertyDescriptor pd2= new PropertyDescriptor(propertyName, rp.getClass());Method methodSetX=pd2.getWriteMethod();methodSetX.invoke(rp,object);}private static Object getObject(Object rp, String propertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {PropertyDescriptor pd= new PropertyDescriptor(propertyName, rp.getClass());Method methodGetX=pd.getReadMethod();Object retValue=methodGetX.invoke(rp);return retValue;}// 复杂的内省public static Object getObject2(Object rp,String propertyName) throws Exception{Object retValue = null;PropertyDescriptor[] pds = Introspector.getBeanInfo(rp.getClass()).getPropertyDescriptors();for (PropertyDescriptor pd : pds) {if (pd.getName().equals(propertyName)) {Method methodGet = pd.getReadMethod();retValue = methodGet.invoke(rp);break;}}return retValue;}





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


0 0
原创粉丝点击