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

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

反射

1、Class 2、反射 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的一个构造函数,有一个参数,类型为StringBuffer
String 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修改为a
	public 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-->time
		setTIME-->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培训、期待与您交流! -------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值