您的位置:首页 > 职场人生

黑马程序员—Java基础加强学习笔记之枚举&反射

2014-04-13 20:59 906 查看

----------- android培训java培训、java学习型技术博客、期待与您交流! -----------  
枚举
1,概念:接口Enumeration<E>



public interface Enumeration<E>

实现 Enumeration 接口的对象,它生成一系列元素,一次生成一个。连续调用
nextElement
方法将返回一系列的连续元素。

例如,要输出 Vector<E> v 的所有元素,可使用以下方法:

  for (Enumeration <E>) e = v.elements (): e.hasMoreElements ():)

System.out.println(e.nextElement());

注:此接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。

2,枚举的理解
 枚举就是Vector特有的取出方式;

 发现枚举和迭代器很像, 其实枚举和迭代器一样;

 因为枚举的名字和方法名都很长,所以后来被迭代器取代

举例:

package com.heima.biji.Demo_enum;
import java.util.Enumeration;
import java.util.Vector;

public class Demo_enum1 {
public static void main(String[] args) {
Vector v = new Vector();
v.add("abc1");//add方法添加元素
v.add("abc2");
v.add("abc3");
Enumeration en = v.elements();//创建枚举迭代器,遍历元素
while(en.hasMoreElements()) {
System.out.println(en.nextElement());
}
}
}结果:

abc1

abc2

abc3


3,注意点:1 枚举相当于一个类,其中也可以定义构造方法、成员变量、普通变量和抽象方法

    2 枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后面要有分号与其他成员分隔开  

4, 枚举的应用举例

    枚举就是要让某个类型的变量取值只能为若干个固定值中的一个,否则,编译器就报错。枚举可以让编译器在编译时期挡住非法元素。

package com.heima.biji.Demo_enum;

public class Demo_enum {
/**
* 枚举基本应用实例:定义星期几的变量该如何定义?假设用1-7表示星期一到星期日,但有人可能会写成int weekday = 0;
*/
public static void main(String[] args) {
WeekDay weekDay =WeekDay.MON;
System.out.println(weekDay);
System.out.println(weekDay.name());//获取元素的名字
System.out.println(weekDay.ordinal());//获取元素的位置
System.out.println(weekDay.valueOf("SUN"));//将字符串调用to.String()
System.out.println(weekDay.values().length);//遍历枚举的元素个数
}
public enum WeekDay{
SUN,MON,TUE,WED,THI,FRI,SAT;
}
}
结果:

MON

MON

1

SUN

7

5,带构造方法和带抽象构造方法的枚举

  举例:

package com.heima.biji.Demo_enum;

public class Demo_enum_gouzaomethod {

public static void main(String[] args) {
WeekDay weekDay =WeekDay.SUN ;
System.out.println(weekDay);
TrafficLamp tf = TrafficLamp.RED;
System.out.println(tf);
}
public enum WeekDay{
SUN(1),MON,TUE,WED,THI,FRI,SAT;//枚举元素,元素后跟(1)表示调用有参构造方法
//,枚举的构造方法必须私有,且顺序在枚举元素后面
private WeekDay() {
System.out.println("空参被调用");
}
private WeekDay(int day) {
System.out.println("有参被调用");
}
}
public enum TrafficLamp {
RED{
@Override
public TrafficLamp nextlamp() {
// TODO Auto-generated method stub
return null;
}
},GREEN {
@Override
public TrafficLamp nextlamp() {
// TODO Auto-generated method stub
return null;
}
},YELLOW{
@Override
public TrafficLamp nextlamp() {
// TODO Auto-generated method stub
return null;
}
};
public abstract TrafficLamp nextlamp();

}
}



反射

1,概念:反射就是把Java类中的各种成分映射成相应的类。
 例如:一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等待信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,轮胎也是一个个类。
表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,有Field、Method、Constructor、Package等待。 
2,Constructor类
Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
例:Constructor [] constructors = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
例: Constructor constructors = Class.forName("java.lang.String")getConstrutor(StringBuffer.class);
 创建实例对象:
通常方式:String str = new String(new StringBUffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBUffer("abc"));
3,成员变量的反射(暴力反射)
Filed类的作用:代表字节码里面的一个变量,不代表某个对象上的变量,知道这个变量后,在各个对象上去取对象身上的变量
4,应用:修改字段
举例:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b''改为"a"

package com.heima.biji.reflect;

public class ReflectPoint {
private int x;//这里定义一个私有的x
public int y;//这里定义一个共有的y
public String str1 = "b1b2";
public String str2 = "b11b22";
public String str3 = "b111b222";

//创建x,y的构造方法
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return str1 + ","+str2+","+str3;
}
}
package com.heima.biji.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;//需要导入反射包\Method方法

public class Demo_reflect {
public static void main(String[] args) throws Exception, SecurityException {
String str1 = "abcdef";
ReflectPoint pt1 = new ReflectPoint(1,2);
Field fieldY= pt1.getClass().getField("y");
//filedY的值是? 是2,错误!!! fieldY不是对象身上的变量,而是类上的,要同它去取某个对象上对应的值
System.out.println(fieldY.get(pt1));

//Field fieldY= pt1.getClass().getField("x");//getField()值能获取共有的,而x被定义私有所以访问不到会报错
Field fieldX= pt1.getClass().getDeclaredField("x");//getDeclaredField()可以获取私有的(不可见的)
fieldX.setAccessible(true);//使用getDeclaredField()后还是不可以,还需要配合setAccessible(flag)
System.out.println(fieldX.get(pt1));//因为x定义为私有,所以直接访问不到
changeStringValue(pt1);
System.out.println(pt1);

}

private static void changeStringValue(Object obj) throws Exception{
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
//if(field1.getType().equals(String.class))
if(field.getType()==String.class){//因为是同一份字节码文件,所以用==
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b','a');//b是old,a是new
field.set(obj, newValue);
}
}

}
}

结果:

2

1

a1a2,a11a22,a111a222

5,Method类代表某个类中的一个成员方法

   得到类中的某个方法:

   例: Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);

调用方法:

通常方式: System.out.println(str.charAt(1));

反射方式:System.out.println(charAt.invoke(str,1));

     
 注意:如果传递给Method对象的invoke()方法的一个参数为null,意义何在?说明该Method对象对应的是一个静态方法!!!(原因推理:静态方法调用时候不需要对象)

    jdk1.4和1.5的invoke方法的区别:

jdk1.4: public Object invoke(Object obj.Obiect ...args)

jdk1.5: public Object invoke(Object obj.Obiect[]args),即按jdk1.4的语法,需要将一个数组做为参数传递给invoke方法时,将数组中的元素对应被调用方法中的一个参数,所以调用charAt方法的代码也可以用jdk1.4的,如:

charAt.invoke("str",new Object[]{1})形式,其中包含自动装箱功能1:new Interger(1)

Method类举例:

package com.heima.biji.reflect;
import java.lang.reflect.Method;//需要导入反射包\Method方法

public class Demo_reflect {
public static void main(String[] args) throws Exception, SecurityException {
String str1 = "abcdef";
//str1.charAt(0),获取字符串中的元素
Method methodCharAt = String.class.getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str1, 0));
System.out.println(methodCharAt.invoke(str1, 1));
//1.4版本是将数组传递给invoke()
System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//自动装箱
}
}

结果:

a

b

c

代码分析:System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//自动装箱;2表示元素列表中第2个角标元素

invoke()调用方法对象上的方法,理解methodCharAt是方法创建的变量对象,表示Method方法,Invoke表示调用此方法,经典理解:司机停车,司机传递信号给汽车,汽车执行刹车动作

----------- android培训[b]、java培训、java学习型技术博客、期待与您交流! ------------  [/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: