反射详解(三种反射获取类的方式)

servlet没有主方法,但是为什么可以运行呢?

因为tomcat有主方法,servlet需要在tomcat上运行,tomcat会进行一系列的调用

用反射:

tomcat不知道我们写的类的名字,没有办法new出来

什么是反射?

拥有分析任何一个类的能力

为什么有反射?

相对于servlet来说;servlet本身没有main方法,为了让我们的servlet响应方法能够运行,我们要有分析类的能力,所以应用反射

一个类有哪些信息?

全局变量、方法、对象、构造器、父类、接口

反射能获取类的哪些信息?

凡是人眼能看到的信息,反射全部可以获取

类和对象之间的关系?

类是构建对象的模板,对象是类的实例化

反射如何获取

为什么类信息储存在方法区当中?

Java源文件先被编译成.class二进制字节码文件

static和类的关系:static修饰的变量、方法都属于类,可以被所有对象共享

this和对象的关系:this代表当前对象

this和static不能够共用

this是当前对象。所以static初始化之后,this才会被创建,static方法是没有this的,

静态方法是整个类的方法,不属于单独的类对象方法,也就是没有this这个指向对象本身的指针。

方法区存储类信息

栈:变量信息

堆:对象

类并不是直接加载到方法区中,而是通过类加载器

反射要想获取类信息,必须生成类对象

反射如何获取类信息?

三种反射获取类的方式

1.通过对象的getClass方法进行获取

2.通过Class.forName()方法获取 //里面填写类的路径 tomcat就是用的这个

        调用静态方法 forName 获得类名对应的 Class 对象。

        String dassName = "java.util .Random";

        Class cl = Class.forName(dassName);

3.通过静态属性class可直接获取到该类型对应的Class对象 例如:T.class 将代表匹配的类对象

面试题:是否能通过反射拿到类的私有信息(暴力反射)

可以,但是这里要设置成true

加入参是因为:只根据名字不能区分两个方法,需要加上参数才能区分方法

package GUI;

import java.lang.reflect.Method;

public class Bdemo {
		public static void main(String[] aaaa) throws Exception {
			Class ca = Class.forName("GUI.Bperson");
			Object xx = ca.newInstance();
			Method aa = ca.getMethod("m1", null);
			aa.invoke(xx, null);
			
			Method aa2 = ca.getMethod("m2",int.class,String.class);
			aa2.invoke(xx,100,"牛牛最帅" );
		}
}
package GUI;

public class Bperson {
	public void m1() {
		System.out.println("嘻嘻");
		
	}
	public void m2(int aa,String bb) {
		System.out.println("嗯嗯" + aa +"," + bb);
		
	}
}

Person
public class Person   {

    //全局变量
    private String name;
    public int age;
    char sex;
    protected int height;

    //带参构造器
    public Person(String name, int age, char sex, int height) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
    }

    //无参构造器
    public Person(){

    }

    public void eat(int num){
        System.out.println("跑的很快");
    }


    private void eat(int num,String name){
        System.out.println("吃的很多");
    }
//同一个类中,拥有同一个方法名,不同的参数列表

    void fly(){
        System.out.println("飞不起来");
    }

    protected void jump(){
        System.out.println("跳的很高");
    }


}

三种反射获取类的方式

//第一种方式,磁盘节点
Class class1 = Class.forName("com.qcby.Reflection.Person");
//第二种方式,类对象阶段
Class class2 = Person.class;//用类名.class
//第三种方式:运行时阶段
Person person = new Person();
Class class3 = person.getClass();//已经生成了对象,用getClass

//用三种阶段的对象获取类信息
System.out.println("这是第一种方式");
Field[] fields1 = class1.getDeclaredFields();
for (Field field:fields1){
    System.out.println(field);
}
System.out.println("这是第二种方式");
Field[] fields2 = class1.getDeclaredFields();
for (Field field:fields2){
    System.out.println(field);
}
System.out.println("这是第三种方式");
Field[] fields3 = class1.getDeclaredFields();
for (Field field:fields3){
    System.out.println(field);
}

反射获取类的全局变量信息的方式(用第一种方式当作例子)

java.lang.NoSuchFieldException异常

有时候使用反射进行Field相关操作的时候会出现这样异常,一般原因有两种:

1.本身就没有该Field;

2.有该Field,但是该Field是使用private修饰的,而在获取该Field的时候,需要使用getDeclaredField这个方法。

//获取全局变量信息的方式
//1.获取类当中所有的全局变量
Field[] fields4 = class1.getDeclaredFields();
for (Field field:fields4){
    System.out.println("获取到的全部的类信息"+fields4);
}

Field[] fields5 = class1.getFields();
for(Field field:fields5){
    System.out.println("获取的全部public类型的类信息"+fields5);
    //getFileds()当前只输出了一个类信息
    //方法名如果加上Declared可以获取全部信息
    //不加只能获取修饰public的信息
}
//获取指定的全局变量
Field[] fieldSex = class1.getDeclaredFields();
System.out.println("获取的指定的类信息(sex)"+fieldSex);

反射获取类的全局变量

1、类.getDeclaredFields()

获取所有的全局变量 需使用field数组接收

2、getFields()

获取所有的public修饰的全局变量 需要使用field数组接收

3、类对象. getDeclaredField("变量名")

能够获取指定的任何修饰符修饰的全局变量信息,需要用filed接收

4、类对象.getFields("变量名")

能够获取指定的public修饰符修饰的全局变量信息,需要使用filed接收

获取类的方法的方式
//如果我们想要获取Person中的eat方法
 Method[] methods = class1.getDeclaredMethods();
 for(Method method:methods){
     System.out.println("获取到的全部的方法的信息"+method);
 }
 Method[] methods1 = class1.getMethods();
 for (Method method:methods1){
     System.out.println("获取到的全部public类型的的方法的信息"+method);
 }
//如果我们想要获取eat

 Method method1=class1.getDeclaredMethod("eat",int.class,String.class);
 System.out.println("获取到的指定的方法的类信息('eat',int.class,String.class"+method1);

 class1.getDeclaredMethod("eat",int.class);  // 正确写法
 class1.getMethod("eat",int.class,String.class); 
 //错误写法 因为getMethod获取指定方法的参数类型错误 getMethod获取的是public的指定的方法信息
 //而有String.class的eat方法是private类型,而不是public类型

获取成员方法的方式

1、 类对象.getDeclaredMethods()

获取所有的 方法信息, Method来接收

2、类对象.getMedthods()

获取public修饰的 方法信息 Method

3、类对象.getDeclaredMethod("方法名",所有参数类型)

获取所有指定的方法信息

4、类对象.getMethod("方法名",所有参数类型)

获取public的指定的方法信息 Method

private Person(int age){ }

Constructor constructor1= class1.getDeclaredConstructor(int.class);
 constructor1.setAccessible(true);
Person person1 = (Person) constructor1.newInstance(1);
 System.out.println("person1="+person1);

总结:构造方法的方式

1、 类对象.getDeclaredConstructors()

获取所有的 方法信息, Constructor来接收

2、类对象.getConstructors()

获取所有的public修饰的 方法信息 Constructor

3、类对象.getDeclaredConstructor("方法名",所有参数类型)

获取所有指定的方法信息

4、类对象.getConstructor("方法名",所有参数类型)

获取public的指定的方法信息 Constructor

如果是private修饰的需要暴力反射,否则会出现报错

constructor1.setAccessible(true);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值