------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
对枚举、可变参数、反射机制、内省的理解
1. 自动装箱和拆箱的理解;
A. Integer it= 213;
B. Integer i3 = Integer.valueOf(213);
以上2种写法都是正确的,a会自动装箱成Integer对象;这个是1.5的新特性;
2. 枚举
A. 枚举是一个类,这里可以说是内部类;枚举里面的每一个元素都是一个对象;
B. 调用枚举类的时候,就会初始化枚举类里面的所有对象,就会调用所有对象对应的构造方法;
C. 在这里我们也可以指定我们的对象调用哪个构造方法,指定的语法是,在对象后面加个(),()传相应的参数;就会调用相应的带参数的构造方法;
D. 枚举类的构造方法必须是私有的;并且枚举里面的构造方法位置,必须放在枚举对象的后面;
E. 字符串变成对象方法WeekDay w =WeekDay.valueOf("SUN")
F. 枚举类获取数组的长度方法;WeekDay.values().length
G. 内部类的应用;
public enum TrafficLamp{
//RED就是父类的引用创建子类的对象,这里有抽象方法,还有复写了抽象方法的具体内容,所以是内部类规则的写法;
//此外这个枚举对象还传递了时间参数,调用了枚举类里面的带参数的构造方法;
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){this.time = time;}
}
3. JDK1.5的特性,可变参数;
A. 可变参数必须放在参数列表的最后面;
B. 可变参数是一个数组,可以用数组的形式打印出来;
C. 可变参数的定义;public static int add(int x,int... args){}
4. 静态导入,JDK1.5的特性;
这个就是不用通过类名去调用方法了,可以直接用;
如;求最大值,平常是用Math. max(3, 6)
通过使用import static java.lang.Math.*; 就可以这么用了max(3, 6)
5. 反射的一些用法;
A. 反射的概念;反射就是把java类中的各种成分映射成相应的java类;
反射的基石——Class类,和calss关键字是有区别的,Class类是类的一个总称,代表java类, Class类里面有很多方法,它和其他的类性质一样;就是一个java类
B. 得到字节码的有三种方式;
要是同一个类的话,这三种方式获取的是同一个字节码;
1)类名.对象; system.class。得到字节码对象;
2)对象.getClass() new Date().getClass();
3)Class.forName("类名") 例如;Class.forName("java.util.Date")
反射一般用第3种方式;
C.
1) type包装着基本数据类型的字节码;所以是一样的字节码;
int.class == Integer.TYPE 他们是一样的字节码;
2) int是基本类型的字节码;int.class == Integer.class
Integer是引用类型的字节码,所以不一样;
3) 这个是数组类型的字节码,不是基本类型字节码,
int[].class.isPrimitive()
4) 比较数组的字节码;数组的维数相同,并且是同一种类型,字节码是相等的;
D. 获取构造方法;
//比如获取这个类的构造方法new String(new StringBuffer("abc"))
我们得到String类的字节码,然后获取String类相应的带有参数的构造函数;StringBuffer.class是表示选择带有StringBuffer类型参数的哪个构造方法;
Constructor constructor1 = String.class.getConstructor
(StringBuffer.class);
E. 通过构造方法,我们创建我们想要的对象,这时需要传递一个对象进去;因为我们需要接收对象,所以要传递;
String str2 =(String)constructor1.newInstance
(new StringBuffer("abc"));
F.
1) 获取对象身上的值要用fieldY.get(pt1),就是说先获取字段,再用字段获取对象上的该字段;
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1))获取x字段值
2) 获取声明过的私有字段方法;
Field fieldX = pt1.getClass().getDeclaredField("x");
设置私有字段上的变量可以访问;这样才能取得私有的字段变量值;
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));获取y字段值;
G. 我们获取反射的方法;
参数charAt是想要获取的方法的名字,第二个参数是想要获取的方法的参数的类型int;所以用int.class;
Method methodCharAt = String.class.getMethod("charAt", int.class);
//再用这个方法去调用我们得到的反射方法;str1是字符串变量,值为abc的话;
那么我们打印出来的值就是abc的第一个位置b;b就是结果;
methodCharAt.invoke(str1, 1)
H. 利用反射的方式来求出元素;能求出数组中的元素,也能求出单个元素;传递什么,就能求出什么;
//打印你给我传递过来的参数;
private static void printObject(Object obj) {
// 得到字节码;
Class 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);
}
}
I. 通过反射的方式,来修改类中字符串的方法;反射机制;我们这里传递的参数是一个类的对象,功能是改变这个类里面变量的值;
private static void changeStringValue(Object obj) throws Exception {
// 获取这个传入类的所有字段;
// Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。
// 反射的字段可能是一个类(静态)字段或实例字段。
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
// 字节码是相等的,所以用== 号;如果这个字段的类型是String类的字节码
if(field.getType() == String.class){
//我们就会通过对象,用字段获取我们的字符串类型的成员变量;field代表的是成员变量;
String oldValue = (String)field.get(obj);
//得到新的串
String newValue = oldValue.replace('b', 'a');
//将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
field.set(obj, newValue);
}
}
}
6. 反射;通过配置文件的用法;
A. getClassLoader()这个是获得类加载器,getResourceAsStream获得资源;
//ips通过决定路径,来获得我们的配置文件,用输入流接收
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");
//通过反射的方式。来获取collections对象;通过不带参数的构造方法方式来获取集合对象;我们的配置文件里面装的是ArrayList它有无参数的构造方法所以可以这么用;
Collection collections (Collection)Class.forName(className).newInstance();
这里我们就可以操作集合。可以添加元素等功能了,要是我们不喜欢ArrayList集合装的元素;在配置文件中也可以换成别的;这样的程序有扩展型;想换集合不用动源码了;直接动配置文件;
7. hashcode的存储模式;
1)Hashcode本身里面有很多区域,我们通过计算hashcode的值,来确定里面的区域,这样可以提高效率。
但是注意一点就是,hashcode元素存储集合完毕后,不能对其进行删除操作,因为我们添加的元素,已经在固定的区域了。你要是修改对象,那么对象就会改变区域,改变后的区域,你删除该对象时候,是找不到的,它默认还户找原来的区域;
这样时间长了,过多的对象不能及时删掉,就会发生内存溢出的现象
2)什么叫做内存泄露,就是有一些对象我们不在用了,但是又没有释放掉,这样就会很占用内存,慢慢的就会发生内存泄露;
举例就是上面1)的例子就可以;
8. 内省
内省就是JDK提供了对javaBean操作的一些API,这套API称之为内省;
javaBean; 就是一个特殊的java类;
含有get和set方法的类,我们称之为javaBean类;也可以当做普通类进行操作;
javaBean的属性名字,是去掉get和set后面的单词;如getAge(){};则javaBean的属性名字为age;
A. 获取javabean的值,和修改javabean的值的第一种方式;
BeanUtils.setProperty(pt1, "birthday.time", "111");//修改对象里面的值
//获得属性字段的名字;
System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));//得到对象里面的值
// 获取x字段的值;
System.out.println(BeanUtils.getProperty(pt1, "x"));
// 修改x字段的值;
BeanUtils.setProperty(pt1, "x", "9");
System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName());//它的结果是String类型
B. 获取javabean的值,和修改javabean的值的第二种方式;
通过PropertyUtils这个工具类;
这个PropertyUtils他是不会转变的类型,如这里的9就是整形,
BeanUtils是帮你转换成字符串类型,这里的"111"就是字符串;这个就是两者是有区别;
PropertyUtils.setProperty(pt1, "x", 9);
System.out.println(PropertyUtils.getProperty(pt1, "x"));
System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());//它的结果是integer类型;