一、反射


反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射的基石:Class类

注意:与小写class的区别,它是定义类时使用的关键字。

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

如何得到各个字节码对应的实例对象(Class类型)三种

创建顺序:字节码在硬盘中——>加载到内存中——>创建对象。

形式:Class class=字节码;

1、Class class1=Date.class;     //固定写法

2、Class class2=new Date().getClass();  //有了字节码创建的对象

3、Class class3=Class.forName(“java.uti.Date”);   //静态方法。(这是主要方式:因为写源程序时还不知道类的名字,写源程序时可以用一个字符串变量,然后从配置文件按中读取)

forName得到类的字节码有两种情况:

  1)、字节码已加载到内存中,无需加载,找到字节码返回。

  2)、虚拟机还没有字节码,用类加载器,将字节码缓存起来(以后无需再加载),使用forName方法获取。

反射具体实现

贴code

要反射的类

package cn.zjy.ClassDemo;

public class ClassDemo {
	 
	 public String name;
	 private static int age;
	 
	
	 
	 public static int getAge() {
		return age;
	}
	public ClassDemo()
     {
    	System.out.println("consruct ClassDemo()"); 
    	this.name = "hahaha";
    	this.age = 18;
     }
     public ClassDemo(String name)
     {
    	 System.out.println("consruct ClassDemo()"+name);
     }
     private ClassDemo(String name ,int age)
     {
    	 System.out.println("consruct ClassDemo()"+age+" "+name); 
    	 this.name=name;
    	 
     }
     
     public void mytest1()
     {
    	System.out.println("implement mytest1"); 
     }
     public void mytest2(String name)
     {
    	 System.out.println("implement mytest2");
     }
     private void mytest3()
     {
    	 System.out.println("implement mytest3"); 
     }
     private static void mytest4()
     {
    	 System.out.println("implement mytest4"); 
     }
     private static void mytest5(String[] args)
     {
    	System.out.println("implement mytest5"); 
     }
}

反射代码


package cn.zjy.ClassDemo;

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

import org.junit.Test;


public class RegexDemo_1 {
	
	
	
    @Test
    public void test1() throws Exception
    {
    	Class myclass = Class.forName("cn.zjy.ClassDemo.ClassDemo");
    	Constructor c = myclass.getConstructor(null);
    	c.newInstance(null);
    }
    @Test
    public void test2() throws Exception
    {
    	Class myclass = Class.forName("cn.zjy.ClassDemo.ClassDemo");
    	Constructor c = myclass.getConstructor(String.class);
    	c.newInstance("hello");
    }
    @Test
    public void test3() throws Exception
    {
    	Class myclass = Class.forName("cn.zjy.ClassDemo.ClassDemo");
    	
    	
    	ClassDemo a1=(ClassDemo)myclass.newInstance();
    //	ClassDemo a2=(ClassDemo)myclass.newInstance("hello");
    	
    	Constructor c = myclass.getDeclaredConstructor(String.class,int.class);
    	c.setAccessible(true);
    	ClassDemo a = (ClassDemo)c.newInstance("hello",1);
    	
    	 System.out.println("the number of construct method is "+ myclass.getDeclaredConstructors().length);
    	 System.out.println("the number of construct method is "+ myclass.getConstructors().length);
    	
    }
    @Test
    public void method_regex() throws Exception
    {
    	Class myclass = ClassDemo.class;
    	ClassDemo demo1=(ClassDemo)myclass.newInstance();
    	
    	Method m1=myclass.getMethod("mytest1",null);
    	m1.invoke(demo1, null);
    	Method m2 = myclass.getMethod("mytest2",String.class);
    	m2.invoke(demo1, "hello");
    	
    	Method m3 = myclass.getDeclaredMethod("mytest3",null);
    	m3.setAccessible(true);
    	m3.invoke(demo1, null);
    	Method m4 = myclass.getDeclaredMethod("mytest4", null);
    	m4.setAccessible(true);
    	m4.invoke(null, null);
    	
    	
    	Method m5=myclass.getDeclaredMethod("mytest5", String[].class);
    	m5.setAccessible(true);
//    	m5.invoke(null, new Object[]{new String[]{"1","2"}});
    	m5.invoke(null, (Object)new String[]{"1","2"});
    }
    @Test
    public void field_test() throws Exception
    {
     	Class demo = ClassDemo.class;
     	ClassDemo mydemo = (ClassDemo)demo.newInstance();
     	
     	Field f1 = demo.getField("name");
     	String name =(String)f1.get(mydemo);
     	System.out.println("i get teh name is "+name);
     	
     	Field f2 = demo.getDeclaredField("age");
     	f2.setAccessible(true);
     	int myage =(Integer)f2.get(null);
     	System.out.println("i get the age is "+myage);
     	
     	f1.set(mydemo,"hello");
     	f2.set(null,20);
     	
     	System.out.println("my name is " + mydemo.name +"my age is "+mydemo.getAge());
      	
    }
    
    
}


二、枚举

枚举类中的声明的每一个枚举值代表枚举类中的一个静态实例对象
枚举类的构造函数必须是私有的
枚举类也可以继承抽象类和接口
注意:枚举值必须放在第一行


为了方便记忆


/*Class MyEnum{
	private MyEnum()
	{};
	public static MyEnum A = new MyEnum();
	public static MyEnum B = new MyEnum();
	public static MyEnum C = new MyEnum();
	public static MyEnum D = new MyEnum();
	public static MyEnum E = new MyEnum();
}*/

在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的。

例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素组成了四季的“数据集”。

在java中如何更好的使用这些“数据集”呢?因此枚举便派上了用场,以下代码详细介绍了枚举的用法。


贴code


enum MyEnum{
	A("a","a"){
		public void mytest()
		{
			System.out.println("name is "+name+"sex is "+sex);
		}
	},B("b","b"){
		public void mytest()
		{
			System.out.println("name is "+name+"sex is "+sex);
		}
		
	},C("c","c"){
		public void mytest()
		{
			System.out.println("name is "+name+"sex is "+sex);
		}
		
	};//必须放在第一行,语法规定
	
	public String name;
	public  String sex;
	private MyEnum(String name,String sex)
	{
		this.name =name ; 
		this.sex = sex;
	}
	public abstract void mytest();//这里定义了一个抽象方法,由枚举常量的内部类来实现,从而实现特定的几个输出。
}



测试类的


package cn.zjy.ClassDemo;

import org.junit.Test;

public class EnumTest {
	@Test
	public void enumtest()
	{
		MyEnum.A.mytest();//可以看到,由于构造函数是私有的,对于这个枚举我们只能调用这三个枚举常量。
		MyEnum.B.mytest();
		MyEnum.C.mytest();
	}
	
}