------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
=================第5单元:反射的深入讲解===============
17.透彻分析反射的基础_Class类
反射的基础:
Class也就是每个java源程序通过编译后生成的文件加载进入内存的那个字节码文件,
获取到该字节码,就可以获取到该Class上的所有信息
获取Class的三种方式:
String str1 = "abc";
1.Class<? extends String> cls1 = str1.getClass();//由对象获取字节码
2.Class<String> cls2 = String.class;//由类名获取字节码
3.Class<?> cls3 = Class.forName("java.lang.String");//反射常用该方式获取,可以通过外部传的参数获取
18.理解反射的概念
19.构造方法的反射应用
获取String str = new String(new StringBuffer("abc"));的构造函数
Constructor<String> constructor1 = String.class
.getConstructor(StringBuffer.class);
// 给该构造器对象实例化,也就是传的参数
String str2 = constructor1.newInstance(/* "abc" */new StringBuffer(
"abc"));
20.成员变量的反射
ReflectPoint pt1 = new ReflectPoint(3, 5);//ReflectPoint类表示一个点
Field fieldY = pt1.getClass().getField("y");// 得到类中的y(public)字段
System.out.println(fieldY.get(pt1));//获取pt1对象上的y字段对应的值 5
Field fieldX = pt1.getClass().getDeclaredField("x");// 得到类中的x(private)字段
fieldX.setAccessible(true);// 重新设置该字段的访问权限,也称为暴力访问
System.out.println(fieldX.get(pt1));//即使是private修饰的字段,通过暴力访问还是可以访问到的
21.成员变量反射的综合案例
通过反射的方式替换成员变量对应的值
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();//获取obj类中的所有字段
for (Field field : fields) {
//是字符串类型的字段进行处理,也就是替换字符串的内容
if (field.getType() == String.class) {
String oldValue = (String) field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
22.成员方法的反射
Method methodCharAt = String.class.getMethod("charAt", int.class);//获取String类中的"charAt方法",参数类型为int
// String str1 = "abc";
System.out.println("methoodCharAt:"+methodCharAt.invoke(str1,1));//等价于 str1.charAt(1);
System.out.println(methodCharAt.invoke(str1, new Object[] { 2 }));
23.对接收数组参数的成员方法进行反射
/*
通过该函数调用其它的函数的main方法
并向调用的main方法中添加参数,打印出添加的参数
*/
public static void main(String[] args) {
String startingClassName = "cn.itcast.day1.TestArguments";//TestArguments类名
Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);//获取函数名为main,参数为String[]的函数
//该参数必须作为一个整体的参数传人
// mainMethod.invoke(null, new Object[]{new
// String[]{"111","222","333"}});
mainMethod.invoke(null, (Object) new String[] { "111", "222", "333" });//调用的是TestArguments类中的main方法
}
class TestArguments {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
24.数组与Object的关系及其反射类型
int[] a1 = new int[] { 1, 2, 3 };
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[] { "a", "b", "c" };
System.out.println(a1.getClass() == a2.getClass());//true
//错误原因:
//每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象
// System.out.println(a1.getClass() == a4.getClass());//error
// System.out.println(a1.getClass() == a3.getClass());//error
System.out.println(a1.getClass().getName());//[I
System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object
System.out.println(a3.getClass().getSuperclass().getName());//java.lang.Object
System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object
//只要父类的类型是Object的就可以给Object赋值
Object aObj1 = a1;
Object aObj2 = a4;
//错误原因:
//a1 的数组中的存放的是基本数据类型,不属于Object类型,故不能用Object的数组存放
// Object[] aObj3 = a1;//error
Object[] aObj4 = a3;
Object[] aObj5 = a4;
25.数组的反射应用
//运用反射打印数组中的数据
private static void printObject(Object obj) {
Class<? extends Object> 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);
}
}
26.ArrayList_HashSet的比较及Hashcode分析
ArrayList是实现了List接口的一个子类,List接口中的元素列表特点:
更确切地讲,列表通常允许满足 e1.equals(e2) 的元素对 e1 和 e2,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素
所有ArrayList 是按照存入顺序有序储存的所以可以存入相同的元素
HashSet 是实现Set接口的一个子类,Set接口中的元素特点:
set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素
HashSet具备了Set集合中的特点,而且它还具备自己的特点:
存入该集合的元素会被通过计算元素的哈希值的不同而存入不同的哈希表区间,所有存入的元素只要哈希值不同,就会被存储进入该集合
所以通常存储该集合的元素都要去覆盖hashCode与equals方法;
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意:参与hashCode运算的元素存入集合时通常不用改变不要改变它的值,这样会引起内存泄漏.
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法
27.框架的概念及用反射技术开发框架的原理
public static void main(String[] args) {
//通过本类把配置信息读入流中
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");//获取配置信息中的className对应的类名
Collection collections = (Collection) Class.forName(className)
.newInstance();//动态的创建Collection对象,而且必须是有空参数的构造方法的才可以
}
28.用类加载器的方式管理资源和配置文件
29.由内省引出JavaBean的讲解
IntroSpector---->JavaBean--->特殊的java类,
就是符合JavaBean规范的类
30.对JavaBean的简单内省操作
//通过传入要操作javabean中的类的对象与属性名
//就可以得到该字段的值
private static Object getProperty(Object pt1, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
//使用的是Javabean中提供的方法
PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
Method methodGetX = pd.getReadMethod();
Object retVal = methodGetX.invoke(pt1);
return retVal;
}
31.对JavaBean的复杂内省操作
//通过传入要操作javabean中的类的对象与属性名,设置该字段的值
private static void setProperties(Object pt1, String propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,
pt1.getClass());
Method methodSetX = pd2.getWriteMethod();
methodSetX.invoke(pt1, value);
}
32.使用BeanUtils工具包操作JavaBean
//Apache提供的对JavaBean操作的类
//设置pt1对象(字段)为x的值为9
BeanUtils.setProperty(pt1, "x", "9");
BeanUtils.getProperty(pt1, "x");