Java反射总结

Java反射就是把java类中的各个组成部分映射成相应的java类。(简单来说,反射机制指的是程序在运行时能够获取自身的信息)。

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

  •         在运行时判断任意一个对象所属的类
  •         在运行时构造任意一个类的对象
  •         在运行时判断任意一个类所具有的成员变量和方法
  •         在运行时调用任意一个对象的方法
  •         生成动态代理 

一、Class类 

想要知道一个类具体的信息,就要先获取到这个类的字节码文件(.class)对应的Class类型的对象。通过Class类中的方法就可以获取类的信息。

1.如何获取一个类的Class实例呢?

方法一: 直接通过一个类的静态变量class获取

Class cls=类名.class

方法二:通过实例变量提供的getClass()方法获取 ,例如:

String a="";
Class cls=a.getClass();

方法三:如果知道一个类的完整类名,可以通过静态方法Class.forName()获取 ,例如:

Class cls=Class.forName("java.lang.String");

一个类的Class实例是在类加载时被创建的,而一个类只会被加载一次,(即Class实例在JVM中是唯一的),所以它的hashCode()值也是唯一的 

 注意:基本数据类型也有Class实例,例如:

 2.Class常用方法

(1)获取包路径:getPackage()

Class cls=DayOfWeek.class;
Package p=cls.getPackage();
if(p!=null) {
			System.out.println("类所在包的名称"+p.getName());
		}

(2)获取类名称:   getName()

Class cls=DayOfWeek.class;
System.out.println("类/接口的完全限定名"+cls.getName());

 (3)获取继承类:   getSuperclass()

Class cls=DayOfWeek.class;
Class sup=cls.getSuperclass();
		System.out.println("类的父类是:"+sup);

(4)获取实现接口:  getInterfaces()

Class[] inter=cls.getInterfaces();
		System.out.println("当前类的实现接口");
		for(Class i:inter) {
			System.out.println(i);
		}

(5)获取构造方法: getConstructor()       Constructor 对象(只能获取共有的构造方法)(括号内可传入参数,传入一个参数就是得到那一个参数相对应的构造方法,不传参数就是获取无参构造方法)

Constructor c1=cls.getConstructor()

getConstructors()       Constructor型数组(只能获取共有的构造方法)

Constructor[] c1=cls.getConstructors()
for(Constructor con:construArray) {
			System.out.println(con);
		}

                               getDeclaredContruector()      Constructor对象(可以获得所有的构造方法,包括私有的和公有的)(括号内输入参数,如果不输入则代表私有的无参构造方法)

Constructor c2=cls.getDeclaredConstructor()

                                getDeclaredContruectors()  Constructor型数组(包括所有的构造方法)

Constructor[] c2=cls.getDeclaredConstructors()

(6)根据反射创建对象:   newInstance()

//		读取类的名称
		String filename=Files.readAllLines(Paths.get("E:\\学习文\\Cup.txt")).get(0);
//		得到类的对象
		Class cls=Class.forName(filename);
//		创建3个对象
//		调用newInstance()相当于  Cup c=new Cup()
//		执行无参构造方法
		Object o1=cls.newInstance();
        Object o2=cls.newInstance();
		Object o3=cls.newInstance();

        System.out.println(o1);
		System.out.println(o2);
		System.out.println(o3);

 (7)获取方法:    getMethods()       Methods型数组

Method[] m=cls.getMethods();

   getDeclaredMethods()         Methods对象

Method[] m=cls.getDeclaredMethods();

(8)获取成员变量:    getFields()       Field型数组

//所有public访问修饰符定义的字段(包括父类的)
Field[] f=cls.getFields();

   getDeclareFileds()        Field对象

//仅包含子类自己的
Field[] f=cls.getDeclaredFields();

二、Constructor类

(1)得到类的所有构造方法

Constructor constructors[]=Class.forName("java.lang.String").getConstructors();//先得到类对应的字节码对象,再得到构造方法

(2)得到类中某个具体的构造方法,在getConstructor中传入参数类型所对应的字节码

Constructor constructor=Class.forName("java.lang.String").getCondtructor(String.class)//得到String 类的 带有一个String类型参数的构造方法

使用Constructor类的目的是:用来创建相应类的对象

  1. 先得到一个类的构造方法;
  2. 然后再通过构造方法创建出类的对象

正常情况(采用反射):String str=new String("hello");

反射情况:

1.先拿到String这个类的带有一个String类型参数的构造方法对象     

Constructor con=String.class.getConstructor(String.class)

2.然后通过构造方法的newInstance()方法创建String类型的对象

String str=(String)con.newInstance("hello")

//传入字符串的值hello并要在前面通过强制类型 转换转换成String 类型的对象

三、Interface 

查询一个类实现的接口

System.out.println("实现接口列表:");
		Class[] cls2=String.class.getInterfaces();
		for(Class c:cls2) {
			System.out.println(c);
		}

四、Field

  1. Class.getFields():得到Class对象的所有字段,返回的是Field数组
  2. Class.getField(String name)返回一个Field对象,它反映此Class对象所表示的类或接口的指定公有成员字段
  3. Field的对象所代表的某一个类的属性,而不是那个类的某一个对象的属性;如果要得到某个对象对应的属性值,需要通过get(Object obj)方法与某个对象具体关联
  4. 对于非公有属性只能通过Class的getDeclaredField(String fieldName)方法得到
  5. 对于私有属性要得到它所关联到的对象的值,通过Field的setAccessible(boolean boolean)方法设置
  6. Field类的getType()方法用来得到字段所属的类型
  7. Field类的getModifiers()方法用来获取成员变量访问修饰符
  8. 如果一个属性是私有属性,则那还需要调用setAccessible(true)来允许访问私有的属性

  9. 给成员变量赋值用set()方法,获取成员变量的值用get()方法

    Class cls=Book.class;
    		
    //		所有public访问修饰符定义的字段(包括父类的)
    //		Field[] f=cls.getFields();
    //		仅包含子类自己的
    		Field[] f=cls.getDeclaredFields();
    		for(Field file:f) {
    			System.out.println("成员变量访问修饰符"+file.getModifiers());
    			System.out.println("成员变量名称:"+file.getName());
    			System.out.println("成员变量类型:"+file.getType());
    			System.out.println("成员变量访问修饰符:"+Modifier.toString(file.getModifiers()));
    			
    		}

 给成员变量赋值:

Book类:

package com.ZhangSha.day10;

public class Book extends Product{
	public String BookName;
	private String auther;
	private double price;
	public double buy(double p,int v) {
		System.out.println("您的会员等级为:"+v);
		System.out.println("打折后价格为:");
		return p*v*0.1;
	}
	private void jie() {
		System.out.println("借书了");
	}
	public void buy() {
		System.out.println("啦啦啦啦买东西了");
	}
	public String getBookName() {
		return BookName;
	}
	public void setBookName(String bookName) {
		BookName = bookName;
	}
	public String getAuther() {
		return auther;
	}
	public void setAuther(String auther) {
		this.auther = auther;
	}
	
	public double getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	@Override
	public String toString() {
		return "Book [BookName=" + BookName + ", auther=" + auther + ", price=" + price + "]";
	}
	public void BookName(String string) {
		// TODO Auto-generated method stub
		
	}
	public Book(String bookName) {
		super();
		BookName = bookName;
	}
	public Book() {
		super();
	}
	
	
	
}
Class cls=Book.class;
		Object obj=cls.newInstance();
//		getField() 获取共有的成员变量
//		getDeclaredField()  获取所有的成员变量(包括共有的和私有的)
//		Field f=cls.getDeclaredField("BookName");
		Field f=cls.getField("BookName");
		f.set(obj, "lalla");
		System.out.println(obj);
		
		Field f2=cls.getDeclaredField("auther");
//		私有的成员变量就要设置setAccessible为true
		f2.setAccessible(true);
		f2.set(obj, "苏涵");
		System.out.println(obj);

 获取成员变量的值:

package com.aPesource.day6;

import java.lang.reflect.Field;

import com.ZhangSha.day10.Book;

public class IS_class5 {
	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
		Book b=new Book();
		b.setBookName("书香");
		b.setAuther("姜邢");
		b.setPrice(87);
		
		printinfo(b);
	}
	public static void printinfo(Object obj) throws IllegalArgumentException, IllegalAccessException {
		Class cls=Book.class;
		Field[] field=cls.getDeclaredFields();
		
		for(Field f:field) {
			System.out.println("成员变量名称:"+f.getName());
			
			if(!f.isAccessible()) {
				f.setAccessible(true);
			}
			System.out.println("成员变量内容:"+f.get(obj));
		}
	}
}

 五、Method类

Method类用来表示类中的方法,通过Class对象的如下方法得到Method对象:

(1)Method getMethod(String name,Class<?>...parameterTypes)//要给出方法的名称和参数所对应的class类型 按名称得到某个特定的public方法(包括从父类或接口继承的方法)

(2)Method[]  getMethods() 得到public方法(包括从父类或接口继承的方法)

(3)Method[] getDeclaredMethods() 得到所有的方法(不包括继承的方法)

(4)Method getDeclaredMethod(String name,Class<?>...parameterTypes) 按名称得到某个特定的方法(不包括继承的方法)

得到Method对象后,需要调用以下方法来在某个对象上执行该方法:

(1)invoke(Object obj,Object obj)第一个是在哪一个对象上调用,第二个是所要调的这个对象所要传入的实参(如果是静态方法则第一个为null)

(1)获取方法 

//反射操作:获取方法
//每一个方法都会被封装成一个Method对象
public class IS_getMethod {
	public static void main(String[] args) {
		Class cls=Book.class;
//		包括继承的父类的所有方法
//		Method[] m=cls.getMethods();
		
//		只包含子类的所有方法
		Method[] m=cls.getDeclaredMethods();
		for(Method method:m) {
			System.out.println("方法的访问修饰符"+Modifier.toString(method.getModifiers()));
			System.out.println("方法的返回值类型"+method.getReturnType());
			System.out.println("方法的名称:"+method.getName());
			
			System.out.println("------------------------");
			
//			获取所有的参数类型
			System.out.println("方法的参数类型:");
			Class[] p=method.getParameterTypes();
			System.out.println(Arrays.toString(p));
			System.out.println("----------------------------------");
			
//			获取所有的参数对象
			Parameter[] p1=method.getParameters();
			for(Parameter para:p1) {
				System.out.println("参数名称"+para.getName());
				System.out.println("参数类型"+para.getType());
			}
		}
	}
}

 (2)调用方法

//反射操作:调用方法
public class IS_getMethod2 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		
		Class cls=Book.class;
		
		Object obj=cls.newInstance();//创建Book对象
		Method m=cls.getMethod("buy",double.class,int.class);
		
//		Method对象的invoke()作用
//		以反射的方式执行create()方法
		double d=(double) m.invoke(obj, 87.6,3);
		System.out.println(d);
	}
}

(3)以反射的方式调用静态方法

//以反射的方式调用静态方法
public class IS_getMethod3 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//		计算以10为底的对数,获取某个数组的位数
		System.out.println(Math.log10(84738)+1);
		
//		反射调用
		Class math=Math.class;
		Method m=math.getMethod("log10", double.class);
		
		int size=Double.valueOf((double)m.invoke(null, 56728283)).intValue()+1;
		System.out.println(size);
	}
}

六、获取继承关系

instanceof  判断是否是什么类型        判断“引用”和“类型”之间的关系

isAssignableFrom   只有父类的引用才可以指向子类的对象,反之则不可     判断“类型”和“类型”之间的关系

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值