Java反射机制部分总结

目录

一、反射定义及用途

1.定义

        1.1 获取当前类的Class对象的方式有三种:

        1.2  通过类的newInstance()方法创建对象

2.用途

二、反射的常用类及其方法

1.Class类

2.Constructor类

 3.Field类

4.Method类

总结:


一、反射定义及用途

1.定义

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

        根据类名,就可以通过该类的newInstance()方法创建对象。

        1.1 获取当前类的Class对象的方式有三种:

                1.直接根据当前类名.class获取

                2.通过getClass()方法获取

                3.通过Class.forName()获取

       

//Class对象的三种获取方式
		//1.通过类名访问
		Class c1=String.class;
		
		//2.通过 getClass()方法访问
		String s="";
		Class c2=s.getClass();
		
		//3,.通过Class的静态方法forName(类名)访问
		Class c3=Class.forName("java.lang.String");
		
		//得到相同的Class对象
		System.out.println("c1="+c1.hashCode());
		System.out.println("c2="+c2.hashCode());
		System.out.println("c3="+c3.hashCode());

        以上三种情况得到的是同一个Class对象。

        1.2  通过类的newInstance()方法创建对象

//利用反射机制创建对象
Object o1=c1.newInstance();
Object o2=c2.newInstance();
Object o3=c3.newInstance();
		

        虽然c1、c2、c3本质都是String的Class对象,但是创建出来的o1、o2、o3是三个不同的对象。

2.用途

        在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法或者为属性赋值。

        Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect 包。          

        (1)在运行时判断任意一个对象所属的类。
        (2)在运行时构造任意一个类的对象。
        (3)在运行时判断任意一个类所具有的成员变量和方法。
        (4)在运行时调用任意一个对象的方法。
        (5)生成动态代理。 

二、反射的常用类及其方法

1.Class类

        (1)理解

        Class类是利用反射机制操作创建对象和后续操作的前提类。class(包括interface)的本质是数据类型(Type)。class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载进内存。每加载一种class,JVM就为其创建一个Class类型的实例,并关联起来。

        class(包括interface)的本质是数据类型(Type)。class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载进内存。每加载一种class,JVM就为其创建一个Class类型的实例,并关联起来。

        Class类的构造方法是私有的,也就是说我们自己不能创建Class示例,仅由Java虚拟机(JVM)可以创建,class(包括interface)的本质是数据类型(Type)。class是由JVM在执行过程中动态加载的。因此,JVM持有的每个Class实例都指向一个数据类型(class或interface)。

        一个Class实例包含了该class的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段(成员变量)等。

       (2)Class常用方法:

类型访问方法返回值类型说明
包路径getPackage()Package对象获取该类的存放路径
类名称getName()String对象获取该类的名称
继承类getSuperclass()Class对象获取该类继承的类
实现接口getInterfaces()Class型数组获取该类实现的所有接口
构造方法getConstructors()Constructor型数组获取所有权限为public的构造方法
构造方法getDeclaredConstructors()Constructor对象获取当前对象的所有构造方法
方法getMethods()Methods型数组获取所有权限为public的方法
方法getDeclaredMethods()Methods对象获取当前对象的所有方法
成员变量getFields()Field型数组获取所有权限为public的成员变量
成员变量getDeclaredFields()Field对象获取当前对象的所有成员变量

       (3)具体代码实现:

public class ClassDemo2 {
	public static void main(String[] args) {
		Class c1=Person.class;
		Class c2=Integer[].class;//数组类
		Class c3=List.class;
		Class c4=DayOfWeek.class;//枚举类
		
		printClassInfo(c1);
		printClassInfo(c2);
		printClassInfo(c3);
		printClassInfo(c4);
		
	}
	
	public static void printClassInfo(Class c) {
		//类名
		System.out.println("类(接口)的名称:"+c.getSimpleName());
		System.out.println("完全限定名:"+c.getName());
		System.out.println("类(接口)的类型名称:"+c.getTypeName());
		
		//父类
		Class superClass=c.getSuperclass();
		System.out.println("类的父类:"+superClass);
		
		//实现的接口
		Class[] interfaceClass=c.getInterfaces();
		System.out.println("当前类实现的接口:");
		for(Class c1:interfaceClass) {
			System.out.println(c1);
		}
		
		//package包
		Package p=c.getPackage();
		if(p!=null) {
			System.out.println("类所在的包名称:"+p.getName());
		}
		
		//判断类型
		System.out.println("是否为接口:"+c.isInterface());
		System.out.println("是否为数组:"+c.isArray());
		System.out.println("是否为枚举:"+c.isEnum());
		System.out.println("是否为基本类型:"+c.isPrimitive());
		System.out.println();
		
	}
}

2.Constructor类

        (1)理解

        它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象是一个构造方法,调用结果总是返回实例。

        (2)Constructor常用方法

方法名及参数说明
getConstructor(Class...)获取某个public的Constructor
getDeclaredConstructor(Class...)获取某个定义的Constructor
getConstructors()获取所有public的Constructor
getDeclaredConstructors()获取所有定义的Constructor

        (3)具体代码实现:

                Example实体类:

public class Example {

	public Example() {
		System.out.println("Example的无参构造方法被加载!");
	}
	
	public Example(int a) {
		System.out.printf("Example的有1个参数的构造方法被加载: a=%d\n ",a);
	}
	public Example(int a,double b) {
		System.out.printf("Example的有2个参数的构造方法被加载:a=%d,b=%.2f\n",a,b);
	}
	private Example(String s) {
		System.out.printf("Example的私有的有参构造方法被加载!s=%s\n",s);
	}
	
	protected Example(float f) {
		System.out.println("Example的受保护的有参构造方法被加载");
	}
}	

                ConstructorDemo类:

public class ConstructorDemo {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		Class class1=Example.class;
		
		//1.调用无参构造
		Example e1=(Example)class1.newInstance();
		
		Constructor[] conStrArray=class1.getConstructors();
		System.out.println("Example的公有构造方法如下:");
		for(Constructor c:conStrArray) {
			System.out.println(c);
		}
		//调用有参构造
		//2.一个参数有参构造
		Constructor c2=class1.getConstructor(int.class);
		Example e2=(Example)c2.newInstance(1);
		System.out.println(e2);
		
		//3.2个参数有参构造
		Constructor c3=class1.getConstructor(int.class,double.class);
		Example e3=(Example)c3.newInstance(1,2.778685);
		System.out.println(e3);
		
	}

}

        结果:

 3.Field类

        (1)理解:字段(成员变量)类。

          (2)   Field类方法

方法名说明
Field getField(name)根据字段名获取当前类中某个public的field(包括父类)
Field getDeclaredField(name)根据字段名获取当前类中定义的某个field(不包括父类)
Field[] getFields()获取所有public的field(包括父类)
Field[] getDeclaredFields()

获取当前类中定义的所有field(不包括父类)

        (3)具体代码实现:

                Order类:

public class Order extends Product{
	private String password;
	public int no;
	public String sex;
	protected String name;
	public String getPassword() {
		return password;
	}
	public int getNo() {
		return no;
	}
	public String getSex() {
		return sex;
	}
	public String getName() {
		return name;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Order [password=" + password + ", no=" + no + ", sex=" + sex + ", name=" + name + "]";
	}
	

	public int dosth() {
		Random rand=new Random();
		return rand.nextInt(100);
	}
	
	public int dosth(int a) {
		Random rand=new Random();
		return rand.nextInt(a);
	}
	
	
}

            FieldsDemo类 :

public class FieldsDemo {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
		Class c1=Order.class;//获取Class类型对象
		
		//1.得到所有public访问字段(成员变量):getFields()方法
		System.out.println("所有访问字段:");
		Field[] zd=c1.getFields();
		
		//2.得到所有的成员变量:getDeclaredFields()方法
		Field[] allzd=c1.getDeclaredFields();
		for(Field f: allzd) {
			System.out.println("------------------");
			System.out.println("成员变量名称:"+f.getName());
			System.out.println("成员变量类型:"+f.getType());
			System.out.println("成员变量的访问修饰符(int值):"+f.getModifiers());
			System.out.println("成员变量的访问修饰符:"+Modifier.toString(f.getModifiers()));
			
		}
		
		//3.设置具体的某个字段的值set()
		Field field1=c1.getDeclaredField("name");//根据字段名来创建字段对象
		if(!field1.isAccessible()) {
			field1.setAccessible(true);
		}
		//通过反射创建对象
		Object obj=c1.newInstance();
		//进行赋值
		field1.set(obj,"刀马旦");
		System.out.println(obj);
		
		
		
		

	}
}

        结果:

4.Method类

        (1)理解:通过Class实例获取所有方法。

        (2)Method类方法:

方法名说明
Method getMethod(name, Class...)获取某个public的Method(包括父类)
Method getDeclaredMethod(name, Class...)获取当前类的某个Method(不包括父类)
Method[] getMethods()获取所有public的Method(包括父类)
Method[] getDeclaredMethods()获取当前类的所有Method(不包括父类)

         (3)具体代码实现:

                MethodsDemo类  

public class MethodsDemo {
	public static void main(String[] args) {
		//拿到Class对象
		Class class1=Order.class;
		
		//拿到所有方法
		System.out.println("该类所有方法如下:");
		System.out.println("--------------");
		
		Method[] methodArray=class1.getMethods();
		//拿到当前类重写的所有方法
		Method[] methods=class1.getDeclaredMethods();
		
		for(Method m:methods) {
			System.out.println("方法的访问修饰符:"+Modifier.toString(m.getModifiers()));
			System.out.println("方法名:"+m.getName());
			System.out.println("方法返回值类型:"+m.getReturnType());
			
			//获取当前方法所有参数
			Parameter[] params=m.getParameters();
			for(Parameter param:params) {
				System.out.println("参数名称:"+param.getName());
				System.out.println("参数类型"+param.getType());
				System.out.println("---------------");
			}
			
			
			
		}
	}
	

}

        结果:

总结:

1.JVM在执行Java程序的时候,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载。

2.通过getConstructor(传入参数类型的不同)得到有参或者无参(不传参)构造方法。

3.得到所有public访问字段(成员变量):getFields()方法

   得到所有的访问字段(成员变量):getDeclaredFields()方法

4.获取所有public的Method(包括父类):getMethods() 方法

    获取当前类的所有Method(不包括父类):getDeclaredMethods()方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值