java反射

反射:
为什么有反射:有时候我们在创建对象时候不知道去创建什么样的对象,以及当时不知道使用什么样的方法的时候,我们希望通过传参来解决这一矛盾,所以反射技术就有了。极大的便于维护。反射对象是通过jvm创建的

什么是反射技术:动态获取类以及类的成员,并动态使用类的成员
* 获取想要的类只要获取到该类的字节码文件即可
* 如何获取字节码文件?
* 答:通过api可以发现java对类也进行了封装,那就是大Class

反射优点:便于维护而且能动态的去操作你要操作的类和方法

反射缺点:可以任意访问私有属性和方法,打破封装性,动态实现,影响程序运行效率。

Class和class的区别: class是java关键词,它是对一个类的描述,比如class Person,而Class又是对class xx的封装。所以Class是对所有class的封装。

反射的获取方式:
实体类:
package domain;

public class Person{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
public Person() {

}
public void show() {
	System.out.println("show run ");
}
public static void staticshow() {
	System.out.println("staitcshow run ");
}
public void paramshow(int age,String name) {
	this.age=age;
	this.name=name;
	System.out.println("paramshow");
}

}

方式一:
import domain.Person;
//字节码文件进内存和静态代码块一样只进内存一次
public class 方式一 {
//类的对象产生都是根据该类的字节码文件进行的,所以就好比字节码对象产生了该类实例对象
//和现实场景相比,母亲创造儿子,那么通过儿子肯定能找到他的母亲
//方式一就是通过创建该类的对象(儿子)找到该类的字节码文件的(母亲)
public static void main(String[] args) {
// TODO Auto-generated method stub
Person p = new Person();
Class c = p.getClass();//c就是该类的字节码文件
System.out.println©;
Person p1 = new Person();
Class c1 = p1.getClass();
System.out.println(c1);
//验证c=c1为true,原理:两个儿子共同的母亲就是同一个人
System.out.println(cc1);//true cc1好比c instanceOf(c1)

}
//方式一的缺点:方式一的原理就是创建该字节码文件的实例子对象来获取该字节码文件使用该字节码文件的
//成员等。依然通过new对象来实现和没用反射没区别

}

方式二:
public class 方式二 {
/*
* java中对每个对象都封装成了一个相应的类型(如 字符封装成Strig)。同样对字节码文件也有描述那就是Class类型
* 那么Class类型里必然有个静态属性用来获取想要的字节码文件,这就是方式二的原理
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//
Class c = Person.class;
//该方法缺点:虽然不用类的实例对象调用,但却用到了类来调用该类的字节码(后面一句话是等价的),他和方式三的区别是方式三的静态初始化块要立刻进内存,而方式二是在 c.newInstacne()才让静态初始化块进内存
}

}

方式三《推荐使用》:
public class 方式三 {

/*
 * 方式三原理:通过Class的方法调用该类的字节码文件
 */
public static void main(String[] args) {
	String className = "domain.Person";//包名加上类名
    Class c = null;
	try {
		c = Class.forName(className);
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
    System.out.println(c);
}

}
/*

  • 方式123的区别:
  • 方式一是通过儿子拿到母亲,方式二是通过自己拿自己
  • 方式三是通过曾祖母拿到母亲
    */

通过反射创建实例对象:
注意:通过反射创建实例对象还是需要借助构造函数的。

无参创建:
public class 创建对象空参构造 {
// 通过反射技术创建对象
public static void main(String[] args)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
String className = “domain.Person”;
Class c = Class.forName(className);
Person p = (Person) c.newInstance();// 这个方法就是等价与new Person();
//而通过newInstance()来创建对象调用的是该对象的空参构造函数如果在person中写了有参构造函数的
//话那么空参构造就没了,那么这句代码就会抛InstantiationException异常
System.out.println§;
}

}

有参构造:
public class 创建对象有参构造 {
//如果该类没有空参构造函数就必须先获取指定的构造函数,斌通过该构造函数进行实例化对象
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String className = “domain.Person”;
Class c = Class.forName(className);
//获得自己想要的构造器
Constructor cons = c.getConstructor(int.class,String.class);
//实例化对象
Person obj = (Person) cons.newInstance(2,“lisi”);
System.out.println(obj.getAge()+obj.getName());
}

}

通过反射调用方法:

一般无参方法:
public class Method {

public static void main(String[] args) throws  Exception, NoSuchMethodException, SecurityException {
	// TODO Auto-generated method stub
	   String className = "domain.Person";
	   Class c = Class.forName(className);//得到字节码
	   //获取方法
	   
	   java.lang.reflect.Method method = c.getMethod("show", null);//第一个为方法名第二个为参数列表
       //得到对象
	   Object obj = c.newInstance();
	   method.invoke(obj, null);//第二个参数是方法的参数列表

}

}

带参方法:

public class ParamMethod {

public static void main(String[] args) throws Exception {
	// TODO Auto-generated method stub
	String className = "domain.Person";
	Class c = Class.forName(className);
	//搞个有参函数并获取
	java.lang.reflect.Method method = c.getMethod("paramshow",int.class,String.class);
	
	//创建对象
	Person obj = (Person) c.newInstance();
	method.invoke(obj, 2,"dddd");
	System.out.println(obj.getAge()+obj.getName());
}

}

静态方法:
public class StaticMethod {

public static void main(String[] args) throws   Exception {
	// TODO Auto-generated method stub
	String className = "domain.Person";
	Class c = Class.forName(className);// 得到字节码
    java.lang.reflect.Method method = c.getMethod("staticshow", null);
     //静态函数不需要创建实例对象来调用的
    method.invoke(null, null);
}

}

通过反射操作属性
public class 动态获取字段 {
public static void main(String[] args) throws Exception, NoSuchFieldException, SecurityException {
String className = “domain.Person”;
Class c = Class.forName(className);//得到字节码
//获取字段getField(“age”);只能获得公共共有的字段私有将会报错
/Field field = c.getField(“age”);
System.out.println(field);
/
//暴力访问,不管权限都可以访问
Field file= c.getDeclaredField(“age”);
System.out.println(file);

    //赋值
    Person obj = (Person) c.newInstance();
  //  file.set(obj, 3);不能赋值会抛异常因为私有了age
    //暴力赋值,利用field的父类access来取消被访问的权限
    file.setAccessible(true);//取消权限
    file.set(obj, 3);
    System.out.println(obj.getAge());

}
}

群里没有课堂代码所以今天笔记我就写我的代码大家可以去向老师要课堂的反射代码。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值