10java基础进阶之反射

本博客写的主要内容的结构,如下:
在这里插入图片描述

反射(Reflection)机制:

能够动态获取类的信息以及动态调用对象的方法。

  • 反射机制主要提供以下功能
  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。

如何实现反射机制:

  • 通常采用java.lang.reflect包中的类来实现
  • Class类:代表一个类,是Reflection API 中的核心类。
  • Field 类:代表类的成员变量(成员变量也称为类的属性)。
  • Method类:代表类的方法。
  • Constructor 类:代表类的构造方法。
  • Array类:提供了动态创建数组,及访问数组的元素的静态方法。

class对象的作用:

  • getName(): 获得类的名称,包括包名
  • getSimpleName(): 获得类的名称,不包括包名
  • getSuperClass(): 获得本类的父类的class对象
  • getInterfaces():获得本类所实现的所有接口的class对象

public Method[] getDeclaredMethods() throws SecurityException
取得所有当前类声明的方法,包括public,protected,默认,private四种访问权限的方法,但是不包括继承的方法

public Method[] getMethods() throws SecurityException
取得所有public的方法,包括继承的,接口中声明的和自己定义的

Field[] getDeclaredFields()
取得所有当前类自己定义的属性,包括四种访问权限的

Field[] getFields()
取得所有public的属性,包括继承的,接口中声明的和自己定义的

代码:

加载Class对象
获取所有公有构造方法
获取公有、无参的构造方法

import java.lang.reflect.Constructor;

public class Constructors {
	public static void main(String[] args) throws Exception {  
        //1.加载Class对象  
        Class clazz = Class.forName("ref.Student");  
   
  /*  //2.获取所有公有构造方法  
    System.out.println("**********************所有公有构造方法*********************************");  
    Constructor[] conArray = clazz.getConstructors();  
    for(Constructor c : conArray){  
        System.out.println(c);  
    }  
      
      
    System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");  
    conArray = clazz.getDeclaredConstructors();  
    for(Constructor c : conArray){  
        System.out.println(c);  
    }  */
      
    System.out.println("*****************获取公有、无参的构造方法*******************************");  
    Constructor con = clazz.getConstructor(null);  
    //1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型  
    //2>、返回的是描述这个无参构造函数的类对象。  
  
    System.out.println("con = " + con);  
    //调用构造方法  
    Object obj = con.newInstance();  
  System.out.println("obj = " + obj);  
  Student stu = (Student)obj;  
  System.out.println(stu.name);
      
    System.out.println("******************获取私有构造方法,并调用*******************************");  
    con = clazz.getDeclaredConstructor(char.class);  
    System.out.println(con);  
    //调用构造方法  
    con.setAccessible(true);//暴力访问(忽略掉访问修饰符)  
    obj = con.newInstance('男');  
//        System.out.println(obj);
//        Student stu2 = (Student)obj;  
//        System.out.println(stu2.name);
    }  
}

获取特定的方法:

import java.lang.reflect.Method;

public class MethodClass {
	public static void main(String[] args) throws Exception {  
        //1.获取Class对象  
        Class stuClass = Class.forName("ref.Student");  
        //2.获取所有公有方法  
        System.out.println("***************获取所有的”公有“方法*******************");  
        stuClass.getMethods();  
        Method[] methodArray = stuClass.getMethods();  
        for(Method m : methodArray){  
            System.out.println(m);  
        }  
        System.out.println("***************获取所有的方法,包括私有的*******************");  
        methodArray = stuClass.getDeclaredMethods();  
        for(Method m : methodArray){  
            System.out.println(m);  
        }  
        System.out.println("***************获取公有的show1()方法*******************");  
        Method m = stuClass.getMethod("show1", String.class);  
        System.out.println(m);  
        //实例化一个Student对象  
        Object obj = stuClass.getConstructor().newInstance();  
        m.invoke(obj, "刘德华");  
          
        System.out.println("***************获取私有的show4()方法******************");  
        m = stuClass.getDeclaredMethod("show4", int.class);  
        System.out.println(m);  
        m.setAccessible(true);//解除私有限定  
        Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参  
        System.out.println("返回值:" + result);     
    }  
}

获取含参的构造函数:

public class Student {
	//---------------构造方法-------------------  
    //(默认的构造方法)  
    Student(String str){  
        System.out.println("(默认)的构造方法 s = " + str);  
    }  
      
//无参构造方法  
public Student(){  
    System.out.println("调用了公有、无参构造方法执行了。。。");  
}  
  
//有一个参数的构造方法  
private Student(char name){  
    System.out.println("姓名:" + name);  
}  
  
//有多个参数的构造方法  
public Student(String name ,int age){  
    System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。  
}  
  
//受保护的构造方法  
protected Student(boolean n){  
    System.out.println("受保护的构造方法 n = " + n);  
}  
  
//私有构造方法  
private Student(int age){  
    System.out.println("私有的构造方法   年龄:"+ age);  
}  

  //**********字段*************//  
    public String name;  
    protected int age;  
    char sex;  
    private String phoneNum;  
  
@Override  
public String toString() {  
    return "Student [name=" + name + ", age=" + age + ", sex=" + sex  
            + ", phoneNum=" + phoneNum + "]";  
}  

//**************成员方法***************//  
public void show1(String s){  
    System.out.println("调用了:公有的,String参数的show1(): s = " + s);  
}  
protected void show2(){  
    System.out.println("调用了:受保护的,无参的show2()");  
}  
void show3(){  
    System.out.println("调用了:默认的,无参的show3()");  
}  
private String show4(int age){  
    System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);  
    return "abcd";  
}  

  //**************main方法***************//  
    public static void main(String[] args) {  
        System.out.println("main方法执行了。。。");  
    }  


public void show(){  
    System.out.println("is show()");  
    }  
}

获取字段(并调用):

import java.lang.reflect.Field;

public class Fields {
	public static void main(String[] args) throws Exception {
		//1.获取Class对象  
	    Class stuClass = Class.forName("ref.Student");  
	    //2.获取字段  
	    /*System.out.println("************获取所有公有的字段********************");  
	    Field[] fieldArray = stuClass.getFields();  
	    for(Field f : fieldArray){  
	        System.out.println(f);  
	    }  
	    System.out.println("************获取所有的字段(包括私有、受保护、默认、公共的)********************");  
	    fieldArray = stuClass.getDeclaredFields();  
	    for(Field f : fieldArray){  
	        System.out.println(f);  
	    } */ 
	    
	    System.out.println("*************获取公有字段**并调用***********************************");  
	    Field f = stuClass.getField("name");  
	    System.out.println(f);  
	    //获取一个对象  
	    Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student();  
	    //为字段设置值  
	    f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华"  
	    //验证  
	    Student stu = (Student)obj;  
	    System.out.println("验证姓名:" + stu.name);  
	      
	      
	    System.out.println("**************获取私有字段****并调用********************************");  
	    f = stuClass.getDeclaredField("phoneNum");  
	    System.out.println(f);  
	    f.setAccessible(true);//暴力反射,解除私有限定  
	    f.set(obj, "18888889999");  
	    System.out.println("验证电话:" + stu);  
	      
	}

获取Class对象:

public class Fanshe {
	public static void main(String[] args) {  
        //第一种方式获取Class对象    
        Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。  
        Class stuClass = stu1.getClass();//获取Class对象  
        System.out.println(stuClass.getName());  
          
        //第二种方式获取Class对象  
        Class stuClass2 = Student.class;  
        System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个  
          
        //第三种方式获取Class对象  
        try {  
            Class stuClass3 = Class.forName("ref.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名  
            System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
          
    }  
}

获取Student对象的字节码
获取main方法
调用main方法

import java.lang.reflect.Method;

public class Main {
	public static void main(String[] args) {
		try {
			//代码对齐:Ctrl+Shift+F   删除选中行代码:Ctrl+D
			
			// 1、获取Student对象的字节码
			Class clazz = Class.forName("ref.Student");

			// 2、获取main方法
			Method methodMain = clazz.getMethod("main", String[].class);// 第一个参数:方法名称,第二个参数:方法形参的类型,
			// 3、调用main方法
			// methodMain.invoke(null, new String[]{"a","b","c"});
			// 第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组,这里要注意在jdk1.4时是数组,jdk1.5之后是可变参数
			// 这里拆的时候将 new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。
			// methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一
			methodMain.invoke(null,new Object[] { new String[] { "a", "b", "c" } });// 方式二

		} catch (Exception e) {
			e.printStackTrace();
		}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值