java高新技术_枚举反射内省(黑马程序员)

------- android培训、java培训、期待与您交流! ----------

我们在java的技术学习中要时刻注意新知识的学习

1.如何传入多个从参数?这里是指可变参数

我们知道1.可变参数只能出现在参数列表的最后。2.。。。位于类型与变量名之间,有无空格均可!

public static void TecDemo_1(int num,String... args)
	{
		System.out.println("一共有"+num+"个参数");
		for(String s:args)
		{
			System.out.print(s);
		}
	}
TecDemo_1(3,"i","love","java");

调用函数获得结果:一共有3个参数ilovejava。本例说明了可变参数和java加强for的使用!

2.枚举

枚举是非常重要的我们可以再定义常量的时候,考虑枚举的使用。我们为了熟悉枚举的使用,先定义一个自己的枚举方式!

//下面是模拟Enum的实现
abstract class weekday
{
	private weekday() {}//在enum中枚举量的构造方法都是私有的,
	public final static weekday mon = new weekday(){

		@Override
		public weekday nextDay() {
			return sun;
		}};//而且枚举量都是常量。可直接引用
	public final static weekday sun = new weekday(){

		@Override
		public weekday nextDay() {
			// TODO Auto-generated method stub
			return mon;
		}};	
	//在枚举中有一些特殊的方法感觉很难,往往把方法定义为一个抽象的这样就可以再
	//自己的匿名子类中复写,比较方便
	public abstract weekday nextDay();
}

我们可以调用我们定义的

public static void TecDemo_2()
	{
		weekday fir = weekday.mon;
		System.out.println(fir);	//com.lxbTestfile.weekday$1@dc8569
		System.out.println(fir.nextDay());//com.lxbTestfile.weekday$2@1bab50a
		//由以上的结果可以看出来那几个mon,sun都是作为子类来实现的!
		//把父类定义为抽象类并没有什么不可以的。
		//这种方法也是enum中的方式,要牢记!
	}

这样的话我们再来使用enum来比较一下我们自己定义的。

//在枚举中可以直接定义抽象类不用加abstract了
enum weekDay
{
	//这里相当于是建立了一个子类的匿名对象;
	mon("this is mon"){	
		@Override
		public  weekDay nextDay()
		{
			return sun;
		}
	},fri("this is fir") {
		@Override
		public weekDay nextDay() {
			return mon;
		}
	},sun("this is sun") {
		@Override
		public weekDay nextDay() {
			return fri;
		}
	};//这就相当于定义的枚举常量
	private String name = null;
	private weekDay(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
	//枚举中增加自己的方法
	public abstract weekDay nextDay();
	
	
}

可以看到的是十分方便,还要注意的是weekDay继承了Enum类是不可以再继承其他的类!如果也其他需求的话继承接口吧!

public static void TecDemo_3()
	{
		weekDay  myf = weekDay.mon;
		System.out.println(myf.name());//枚举中自己的名称函数
		System.out.println(myf.ordinal());//获得在枚举中的index
		System.out.println(myf.getName());//自己定的名称函数
		System.out.println(myf.nextDay());
	}
这里调用了函数来使用我们的枚举类!

你把枚举成员定义为一个的时候,看看是什么?好的,的确,枚举可以作为单例来使用!

3.我们来看一下反射,反射的意思就是把class中的东西映射为可操作的方法;主要有构造函数Constructor,方法Method,字段Field。

如何获得constructor呢?也就是如何获得构造方法?

//下面是够造class的3种方式:然后又获得了构造方法!
		//Constructor myconstructor = String.class.getConstructor(StringBuilder.class);
		//Constructor myconstructor = "class".getClass().getConstructor(StringBuilder.class);
		Constructor myconstructor = Class.forName("java.lang.String").getConstructor(StringBuilder.class);
		String mystr = (String) myconstructor.newInstance(new StringBuilder("abc"));//如何让调用构造方法!
		System.out.println(mystr);

上述例子中也说明了如何获得class对象的3种方法:1.对象.getClass()。2.类名.Class。3.Class.forNAme("对象所在包")。

构造方法获得后,调用newInstance()可以调用构造方法。产生对象!

如何获得字段?

refPoint ref = new refPoint();
		Field myf = refPoint.class.getField("num2");//获得字段的class反射
		myf.set(ref, "banana");//可以修改字段!
		String mystr2 = (String) myf.get(ref);//有反射获得对象字段的值!
		System.out.println(mystr2);
		//下面为暴力反射的例子	
		Field myf2 = ref.getClass().getDeclaredField("num1");
		myf2.setAccessible(true);//由于num1为private所以要设为可见!
		String mystr3 = (String) myf2.get(ref);
		System.out.println(mystr3);

首先来说明refPoint是什么吧

class refPoint
{
	private String num1 = "mango";
	public  String num2 = "apple";
	public void sop(String[] str)
	{
		for(String s:str)
		System.out.println(s);
	}
}

获取字段还是比较简单的,调用getField方法就可以获得某一个字段了,调用get或者是set就可以修改;

注意的是在对象中private字段是不可见的,我们可以用暴力反射来解决!

下面看一下获得方法:

//在方法反射中要注意的是调用invoke方法就是调用原来的方法!
		Method mym = String.class.getMethod("charAt",int.class);
		System.out.println( mym.invoke("abs",1));
		 System.out.println( mym.invoke("abs",new Object[]{2}));
		 //如果参数方法第一个参数为null认为是静态方法!
		 Method mym2 = Integer.class.getMethod("toString", null);
		 System.out.println(mym2.invoke(2, null));
		 //要注意的是在反射方法的时候如果传入的是一个数组,那么会有不同的现象
		 //也就是说如果是对象的数组要加(Object),以免java认为传入多个参数!
		 Method mym3 = ref.getClass().getMethod("sop", String[].class);
		 mym3.invoke(ref,(Object)new String[]{"hello","world"});

调用getMethod就可以了,要注意代码注释的传入数组的时候要小心!

那么如何反射数组呢?

//数组的class只和数组的类型和维度有关
		 int[] numbe = new int[]{1};//也就是说numb和number的getClass()是一样的
		 int[] number = new int[]{1,2,3};
		 String[] strber = new String[]{"i","love","java"};
		 	//数组的反射是利用Array来实现的
		 System.out.println(Array.getLength(number));//获取数组长度
		 System.out.println(Array.get(strber, 2));//获取数组的成员

数组的反射是靠Array来实现的,注意一下Arrays。asList()方法也是很有用的!

4内省机制(introspector)是为了方便处理javabean。如何利用内省来处理javaBean?首先来看一个javaBean

class loveperson
{
	public loveperson(String name,int age)
	{
		this.name = name;
		this.age =age;
	}
	private String name;
	private int age ;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}	
}

还是比较简单的。如何在程序中处理呢?

public static void TecDemo_5() throws Exception 
	{
		//这是第一种方法操作javabean,用的是PropertyDescriptor对象
		loveperson p = new loveperson("lxb",15);
		PropertyDescriptor proDes = new PropertyDescriptor("name",p.getClass());//利用类和类的属性名做参数生成一个对象
		Method m = proDes.getReadMethod();//那个获取读的方法
		Method m1 = proDes.getWriteMethod();//获取写的方法
		String myname = (String) m.invoke(p);//调用读的方法
		m1.invoke(p,"bxl");//调用写的方法
		System.out.println(myname);
		System.out.println(p.getName());
		
		//下面用一种老的方法来进行操作
		BeanInfo binfo = Introspector.getBeanInfo(p.getClass());//首先获得一个beanInfo对象
		PropertyDescriptor[] pDes = binfo.getPropertyDescriptors();//通过beanInfo来获得PropertyDescriptor!
		for(PropertyDescriptor pd:pDes)
		{
			if(pd.getName().equals("name"))
			{
				Method m3 = pd.getReadMethod();
				String myname2 = (String) m3.invoke(p);
				System.out.println(myname2);
			}
		}
	}

在代码中我给除了两种方法。推荐用第一种!第二种是十分繁琐的,所以你要来接即可!

在内省中要合理运用PropertyDescriptor来处理!主要就是getReadMethod和getWriteMethod的使用



------- android培训、java培训、期待与您交流! ----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值