Java--枚举与反射

枚举示例:

package li.dao.fu.test.enums;

/*
 * 枚举是一种特殊形式的java类
 * 枚举中声明的每一个枚举值代表枚举类的一个实例对象
 * 与java普通类一样,在声明枚举类时,也可以声明属性,方法和构造函数,但枚举的构造函数必须为私有的
 * 枚举也可以实现接口,或继承抽象类
 * 若枚举中只有一个值可以当成单例设计模式
 * */
public enum EnumTest {
	
	A(90,100){
		//实现抽象方法
		public String getLevel(){
			return "优秀";
		}
	},
	B(80,90){
		public String getLevel(){
			return "良好";
		}
	},
	C(70,80){
		public String getLevel(){
			return "一般";
		}
	},
	D(60,70){
		public String getLevel(){
			return "及格";
		}
	},
	E(0,60){
		public String getLevel(){
			return "不及格";
		}
	};
	
	private int minScore;
	private int maxScore;
	//枚举的构造函数必须是私有的,这是因为它不能被外界所实例化,只能是固定的那几个实例,不能改变
	private EnumTest(int minScore,int maxScore){
		this.minScore=minScore;
		this.maxScore=maxScore;
	}
	public int getMin(){
		return this.minScore;
	}
	public int getMax(){
		return this.maxScore;
	}
	//枚举中定义的抽象方法,必须在每个实例中实现这个方法
	public abstract String getLevel();
}
package li.dao.fu.test.enums;


public class Test {

	public static void main(String[] args) {
		
		System.out.println("Grade Level:");
		String[] chs={"A","B","C","D","E"};
		for(int i=0;i<chs.length;i++){
			//根据指定的字符串返回相应的枚举实例
			EnumTest TEMP=EnumTest.valueOf(chs[i]);
			//name:返回相应枚举实例的名字
			System.out.println(TEMP.name()+":"+TEMP.getLevel());
			System.out.println(TEMP.getMin()+"-"+TEMP.getMax());
		}
		
		//枚举类有一个隐含的方法values,返回所有枚举实例,但API没有写出这个方法
		EnumTest[] enums=EnumTest.values();
		for(int i=0;i<enums.length;i++){
			if(enums[i].name()=="D"){
				System.out.println(enums[i].getMin()+"-"+enums[i].getMax());
			}
		}
		
		//返回枚举实例对应的索引
		int index=EnumTest.C.ordinal();
		System.out.println("index:"+index);
			
	}

}

 

反射示例:

package li.dao.fu.test.reflect;

public class Person {
	
	public String name;
	public int age;
	
	public  Person(){
		System.out.println("no parameter");
	}
	private Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	public void show(String message){
		System.out.println("message:"+message);
		System.out.println("name:"+this.name+" age:"+this.age);
	}
	private void out(){
		System.out.println("name:"+this.name+" age:"+this.age);
	}
	
	public static void print(String message){
		System.out.println("message:"+message);
	}
	
	public static int getMax(int[] nums){
		int max=nums[0];
		for(int i=1;i<nums.length;i++){
			if(nums[i]>max)
				max=nums[i];
		}
		return max;
	}
	
	public static String getMaxLength(String[] strs){
		int max=0;
		for(int i=1;i<strs.length;i++){
			if(strs[i].length()>strs[max].length())
				max=i;
		}
		return strs[max];
	}
}
package li.dao.fu.test.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectTest {
	/*
	 * 利用反射创建对象的三个步骤:
	 * 1.获得类的Class文件
	 * 		三种方式可获得class文件:
	 * 		a.利用静态方法:Class.forName(类名),类名必须是类的全名包括包名
	 * 		b.类名.Class()
	 * 		c.对象名.getClass()
	 * 2,利用Class文件获取构造函数
	 * 		二种方式:
	 * 		a.getConstructor(Class...):获取类的公有的构造函数,无法获取非public的构造函数
	 * 		b.getDeclaredConstructor(Class...):获取类的所有构造函数,只要类中声明了就可获取
	 * 3.利用构造函数实例化
	 * 	 newInstance(参数);注意:如果构造函数是通过getDeclaredConstructor()方法获得的,那么
	 * 	 在用这个构造函数创建对象时,要先设定它的访问权限为true即setAccessible(true);暴力访问
	 * 
	 * 为了方便利用反射来创建对象,API还提供了一个newInstance()方法来创建对象,可以直接通过Class文件来
	 * 创建对象,类Class.newInstance();但这个种方式只能创建无参的对象,并且这个 类的无参构造函数必须是公有的
	 * 
	 * 
	 * 利用反射调用方法
	 * 	 方法步骤和利用反射创建对象步骤相似
	 * 注意点:
	 * 		a.在获取方法或在调用方法时,如果方法无参数可以不写或者写null;
	 * 		b.在调用静态的方法时,调用对象可以写null;
	 * 		c.在调用方法即调用invoke方法时,要注意如果给方法传递的是非基本数据类型的数组时,要将这个数组转换
	 * 		      成Object对象或打包成一个新的数组;这是因为在JDK1.4中invoke(Object obj,Object[] objs)
	 * 		     方法中的objs参数是一个Object数组,invoke方法会将这个数组拆开然后将值传递给方法,所以如果要调用
	 * 		     的方法需要的是一个数组时就无法传递进去,所以如果要传递一个数组给方法时,必须先要将这个数组打包成一个新的数组
	 * 		     这样当invoke拆开这个数组时,里面还是个数组,就可以将数组传递过去了,当然也可以将这个数组转换成一个对象,
	 * 		  invoke方法看到传递的是一个对象时就不会拆开这个对象了	
	 * 
	 * 
	 * 
	 * */
	public static void main(String[] args) throws Exception {
		//获取Class文件
		Class<?> claxx=Class.forName("li.dao.fu.test.reflect.Person");
		//利用class文件获取所需的构造函数
		//Constructor<?> con=claxx.getConstructor(null);
		//创建对象
		//Person p=(Person) con.newInstance(null);
		
		//获取非公有的构造函数
		Constructor<?> con1=claxx.getDeclaredConstructor(String.class,int.class);
		//将访问权限高为true,即暴力反射
		con1.setAccessible(true);
		//创建对象
		Person p1=(Person) con1.newInstance("lidaofu",24);
		
	
		
		//获取类的所有公有方法
		Method[] methods=claxx.getMethods();
		for(Method method:methods){
			System.out.println(method.getName());
		}
		
		//访问私有无参数的方法
		//暴力访问类中的私有方法,getDeclaredMethod方法的第一个参数为要获取的方法名,第二个为方法的参数类型class对象,如果为无参函数则为null或者不写
		Method method=claxx.getDeclaredMethod("out");
		//将访问权限设为true
		method.setAccessible(true);
		//调用方法,invoke方法的第一个参数为调用该方法的对象,第二个是为该方法指定的参数,如果是无参函数可以不写或写null
		method.invoke(p1);	//method.invoke(p1,null);
		
		
		//访问公有有参数的方法
		Method method2=claxx.getMethod("show", String.class);
		//指明调用该方法的对象和为对象的赋值
		method2.invoke(p1, "调用有参数的方法");
		
		//调用静态有参数的方法
		Method method3=claxx.getMethod("print",String.class);
		//调用静态方法时,可以不指定调用的对象,写null即可
		method3.invoke(null, "静态方法调用");
		
		//调用静态参数为基本数据类型的数组的方法
		Method method4=claxx.getMethod("getMax",int[].class);
		//这里传递的数组是基本数据类型的数组,可以不用转换成一个对象或者打包成一个新的数组
		Integer max=(Integer)method4.invoke(null, new int[]{2,6,1,7,5,9});
		System.out.println("max="+max);
		
		//调用静态参数为非基本数据类型的数组的方法
		Method method5=claxx.getMethod("getMaxLength", String[].class);
		//这里在传递非基本数据类型的数组参数时,要注意应该将这个参数数组打包成一个新数组或或者转换成一个Object对象传递过去,这是为了兼容JDK1.4,不然后出现异常
		String maxLength=(String)method5.invoke(null,new Object[]{new String[]{"av","haha","iloveyou"}});
		//这里也可以改成这样的形式:invoke(null,Object(new String[]{"av","haha","iloveyou"}));
		System.out.println(maxLength);
		
		
		//获取类上的所有公有字段
		Field[] fields=claxx.getFields();
		for(int i=0;i<fields.length;i++){
			Field field=fields[i];
			//打印字段名称和字段值
			System.out.println(field.getName()+":"+field.get(p1));
		}
		
		
		
	}

}


 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值