`
modabobo
  • 浏览: 506075 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

-----------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培训java培训java学习型技术博客、期待与您交流!------------

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics