zoukankan      html  css  js  c++  java
  • java 反射详解

    目录

    反射定义
    反射实现
    通过反射获取对应类的Class对象
    根据对应类的Class对象得到全限定名、类名、包名
    获取类的所有实现接口
    获取类的属性(Filed 类)
    通过Class对象构造对应的实例对象(不通过new)
    修改或获取指定对象的属性
    获取类的方法 (Method 类)
    构造方法相关操作

    反射定义

    反射式在java程序运行时,我还能动态的得到某个对象的所有属性和方法信息。并且可以动态执行某个对象的指定方法,或修改指定属性。这就是反射。

    java反射实现

    首先定义我们的操作类,Person

    public class Person  implements Serializable{
    	/**
    	 * 序列化  序列化编号
    	 */
    	private static final long serialVersionUID = -5293639382415756109L;
    	public int pid;
    	private String pname;
    	
    	public Person() {
    		
    	}
    	public Person(String name) {
    		this.pname = name;
    	}
    	
    	public Person(int pid, String pname) {
    		this.pid = pid;
    		this.pname = pname;
    	}
    	public String getPname() {
    		return pname;
    	}
    	
    	//getPid是一个私有的方法
    	public int getPid() {
    		return pid;
    	}
    	
    	public void setPid(int pid) {
    		this.pid = pid;
    	}
    	
    	public void setPname(String pname) {
    		this.pname = pname;
    	}
    	
    	//add是一个私有的方法
    	private String add(Integer i, Integer j) {
    		return i + j + "";
    	}
    }
    

    通过反射获取对应类的Class对象

    class对象在类加载时会由虚拟机内部产生,并且一个类有且只有一个对应的class对象。还有 基础数据类型、数组、包括关键字 void (void.class)都有对应的class对象.下面我们看看如何获取class对象

    		//(1)类.class
    		 Class c = Person.class;
    		 
    		// (2)对象名.getClass()
    		 Person person = new Person();
    		 Class c2 = person.getClass();
    	
    		// (3)Class.forName("全限定名")
    		// 全限定名 一定是包含包名的 包名.类名
    		 Class c3 = Class.forName("com.cpc.temp.Person");
    	
    		// (4)类.getClassLoader().loadClass("全限定名")
    		 Class c4 = Person.class.getClassLoader().loadClass("com.cpc.temp.Person");
    
    		// (5)子类.class.getSuperClass()
    		// 这是等到父类class对象  (这返回的是Object的Class对象)
    		Class c5 = Person.class.getSuperclass();
    		
    		// (6)包装类.class
    		Class c6 = Integer.class;
    

    根据对应类的Class对象得到全限定名、类名、包名

    		 Class c1 = Class.forName("com.cpc.temp.Person");
    		 System.out.println("全限定名" + c1.getName());
    		 System.out.println("类名" + c1.getSimpleName());
    		 System.out.println("包名" + c1.getPackage());
    

    执行结果

    全限定名com.cpc.temp.Person
    类名Person
    报名package com.cpc.temp
    

    获取类的所有实现接口

    		 Class c1 =  Person.class;
    		 //这是所有接口对应的Class对象数组
    		 Class[] classin = c1.getInterfaces();
    		 //遍历
    		 for(int i = 0; i < classin.length; i ++) {
    			 System.out.println(classin[i].getName());
    		 }
    

    执行结果

    java.io.Serializable
    

    获取类的属性(Filed 类)

    获取Class对象的属性返回的就是Filed类实例

    		// 4获取类的属性(Filed 类)
    		Class c1 = Person.class;
    		// getField("属性名") 获取公有属性
    		System.out.println("---------获取公有属性--------");
    		Field pid = c1.getField("pid");
    		// getName() 获取属性名
    		System.out.println("pid的属性名" + pid.getName());
    		// getModifiers() 获取访问修改符
    		System.out.println("pid的访问修饰符" + pid.getModifiers());
    		// 上面的getModifiers输出结果是数字,对应的修饰符就是下面几个常量值
    		System.out.println("----属性访问修饰符------");
    		System.out.println("public:" + Modifier.PUBLIC);
    		System.out.println("private:" + Modifier.PRIVATE);
    		System.out.println("protected:" + Modifier.PROTECTED);
    		
    		// getType() 获取属性的类型对应的Class对象
    		System.out.println("----获取属性的类型对应的Class对象------");
    		Class cla = pid.getType();
    		System.out.println(cla.getName());
    		
    		// getDeclaredField("属性名") 获取私有属性值
    		Field pname = c1.getDeclaredField("pname");
    		System.out.println("-----获取私有属性----");
    		//输出属性名
    		System.out.println(pname.getName());
    		//输出属性的访问修饰符
    		System.out.println(pname.getModifiers());
    		//setAccessible(true) 设置私有属性可访问
    		pname.setAccessible(true);
    		pname.set(person, "zs");
    		System.out.println(person.getPname());
    		
    		// getDeclaredFields() 获取所有的属性(公有私有都能获取到)
    		Field[] fileds = c1.getDeclaredFields();
    		System.out.println("------遍历所有属性,并输出属性名-----");
    		for (Field field : fileds) {
    			System.out.println(field.getName());
    		}
    

    执行结果

    ---------获取公有属性--------
    pid的属性名pid
    pid的访问修饰符1
    ----属性访问修饰符------
    public:1
    private:2
    protected:4
    ----获取属性的类型对应的Class对象------
    int
    -----获取私有属性----
    pname
    2
    zs
    ------遍历所有属性,并输出属性名-----
    serialVersionUID
    pid
    pname
    
    

    通过Class对象构造对应的实例对象(不通过new)

    		Class c1 = Person.class;
    		Person p = (Person)c1.newInstance();
    

    修改或获取指定对象的属性

    		Class c1 = Person.class;
    		Field pid = c1.getField("pid");
    		Person p = (Person) c1.newInstance();
    		// 修改person的
    		pid.set(person, 1);
    		//// get(对象名)=对象名.get属性名 获取属性值
    		System.out.println(pid.get(person));
    

    执行结果

    1
    

    获取类的方法 (Method 类)

    		Class c1 = Person.class;
    		Object object = c1.newInstance();
    		// getMethod(方法名,参数数据类型(无参数传Null)) 获取公共方法
    		Method setPid = c1.getMethod("setPid", int.class);
    		// invok (对象名, 参数列表)=对象名.方法名 执行方法
    		setPid.invoke(object, 1);
    		Method getPid = c1.getMethod("getPid", null);
    		System.out.println("执行公共getPid返回结果:" + getPid.invoke(object, null));
    
    		// getDeclaredMethod(方法名,参数数据类型(无参数传null)) 获取私有方法
    		Method add = c1.getDeclaredMethod("add", Integer.class, Integer.class);
    		add.setAccessible(true);
    		System.out.println("执行私有add返回结果:" + add.invoke(object, 1, 2));
    		// getReturnType() 得到返回值方法的数据类型的Class对象
    		Class re = add.getReturnType();
    		System.out.println("add方法的返回类型"+re.getName());
    
    		// getParameterTypes() 得到方法参数列表()
    		Class[] cal = add.getParameterTypes();
    		System.out.println("----遍历add的参数列表------开始");
    		for (Class cc : cal) {
    			System.out.println(cc.getName());
    		}
    		System.out.println("----遍历add的参数列表------结束");
    		// getDeclaredMethods() 得到类的所有方法
    		Method[] methods = c1.getDeclaredMethods();
    		System.out.println("-----遍历所有方法----开始");
    		for (Method method : methods) {
    			System.out.println(method.getName());
    		}
    		System.out.println("-----遍历所有方法-----结束");
    

    执行结果

    执行公共getPid返回结果:1
    执行私有add方法:3
    add方法的返回类型java.lang.String
    ----遍历add的参数列表------开始
    java.lang.Integer
    java.lang.Integer
    ----遍历add的参数列表------结束
    -----遍历所有方法----开始
    add
    setPid
    getPname
    getPid
    setPname
    -----遍历所有方法-----结束
    

    构造方法相关操作

    		Class c1 = Person.class;
    		// getConstructor 得到构造方法
    		Constructor con = c1.getConstructor(int.class, String.class);
    		// 通过指定构造方法构造对象
    		Person p1 = (Person) con.newInstance(1, "张三");
    		System.out.println("获取通过指定构造方法构造出来的p1对象的属性");
    		System.out.println(p1.getPid());
    		System.out.println(p1.getPname());
    		// gitConstructors 获取所有构造方法 并输出构造方法的参数个数
    		Constructor[] constructors = c1.getConstructors();
    		System.out.println("------遍历构造方法-----");
    		for (Constructor constructor : constructors) {
    			System.out.println(constructor.getParameterCount());
    		}
    

    执行结果

    获取通过指定构造方法构造出来的p1对象的属性
    1
    张三
    ------遍历构造方法-----
    2
    1
    0
    

    其余的操作和方法操作差不多,这里就不过的赘述了.

    如果有不对的地方欢迎在留言区批评指正。如果觉得对请点个赞那是对我最大的支持~~

  • 相关阅读:
    JAVA编程-------29、求3*3矩阵对角线元素之和
    JAVA编程---------28、对10个数进行排序(冒泡排序)
    JAVA编程-------------27、100以内的素数
    JAVA编程----------26、请输入星期几的第一个字母来判断一下星期几, 第一个字母相同,则判断第二个字母,以此类推
    JAVA编程-----------25、查找5位数的回文数
    JAVA编程---------24、输入一个数,判断位数,并逆序输出
    JAVA编程------------23、递归
    JAVA编程------------22、利用递归求5!
    JAVA编程--------21、求1!+2!+....+20!=
    JAVA编程------------20、计算2/1+3/2+5/3+8/5+...求前20项之和
  • 原文地址:https://www.cnblogs.com/IT-CPC/p/10957243.html
Copyright © 2011-2022 走看看