java基础之反射reflection

Java基础反射


一、前言

   反射机制的存在允许程序在执行期借助reflection API来实现获取任何类的内部信息,并能直接操作任意对象的内部属性及方法,简而言之就是不采取常规的new一个对象来实现对象的创建,而是用类来创建对象操作对象,使用场景往往是编写代码时部分功能还不确定何时被使用?哪一部分会被使用?(什么时候用?用哪一个的问题)

二、反射提供的功能

  1. 对象的创建
  2. 获取类的属性
  3. 获取类内部的方法
  4. 判断一个对象所属的类
  5. 获取泛型信息
  6. 处理注解
  7. 生成动态代理

反射所提供的功能都发生在程序的运行过程当中,实时动态的处理对象的有关问题

三、相关API

Java.lang.Class:代表一个类
Java.lang.reflect.Method:代表类的方法
Java.lang.reflect.Field:代表成员变量
Java.lang.reflect.Constructor:代表类的构造器

四、class类

  1. 在object类中定义的方法
    public final Class getClass()
    
    该方法被所有的类继承,此方法返回的类就是一个class类
  2. class类的常用方法
    class类的内部方法
  • newInstance():通过调用无参构造器实现实例化
Class personClass = person.class;
Object o = personClass.newInstance();
System.out.println(o.toString());

结果:调用方法的结果

五、实例

	@Test
    public void test1() throws Exception {
    	//获取对象的class类
        Class personClass = person.class;
		
		//获得类的名称
        String name = personClass.getName();
        System.out.println(name);

		 //直接获取无参对象
        Object o = personClass.newInstance();
        System.out.println(o.toString());

        //通过反射创建对象
        	//获得构造器
        Constructor constructor = personClass.getDeclaredConstructor(String.class,String.class);
        	//通过构造器创建对象
        Object tom = constructor.newInstance("tom","12");
        	//调用对应的属性
        Field age = personClass.getDeclaredField("age");
        age.setAccessible(true);
        age.set(tom, "10");
        	//调用方法
        Method show = personClass.getDeclaredMethod("show");
        show.setAccessible(true);
        show.invoke(tom);
        //输出tom的信息
        System.out.println(tom);
    }
public class person {
    private String name;
    private String age;

    public person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    private person(String name) {
        this.name = name;
    }

    public person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public void show(){
        System.out.println("这是show方法!!");
    }

    @Override
    public String toString() {
        return "person{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

六、发现的一些问题

正常情况下通过反射的方式可以拿到对象的私有属性和私有的方法,而常规方法是无法使用类内部私有的方法和属性,但是如果用错方法就还是拿不到这些私有的东东
譬如:

 Field age = personClass.getField("age");
 //当我们调用的是getField方法时,该属性只能是public修饰
 //如果想获得的属性是private的话,只能用getDeclaredField方法来获取


同理在调用构造器和方法时也要注意这个问题

七、在项目中发现的一些东西

咳咳…后面才是今天得正题
前端页面我写了一个表单是这样的:

<form action="userServlet" method="post">
	<input type="hidden" name="action" value="login" />
	<label>用户名称:</label>
	<input class="itxt" type="text" placeholder="请输入用户名"
		   autocomplete="off" tabindex="1" name="username"
		   value="${requestScope.username}" />
	<br />
	<br />
	<label>用户密码:</label>
	<input class="itxt" type="password" placeholder="请输入密码"
		   autocomplete="off" tabindex="1" name="password" />
	<br />
	<br />
	<input type="submit" value="登录" id="sub_btn" />
</form>
   这个页面我觉得大部分人都可以读懂,主要想说的是在这里我是用了一个隐藏域hidden,提交了一个键值对< action login >,有没想过为什么要传这样一个值呢?
   接下来讨论得是Javaweb原生得一些东西,虽然我知道后边得springboot等一些框架在这方面已经做的很好了,但是我仍认为这是一种懒汉方式,有些注解只是知道怎么用还是不行的,现在我们就javaweb这种原生的方式来说一下怎么解决servlet的映射问题

一个servlet应用中可能包含多种方法,但是映射关系确是
	<servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>com.warrior.web.testServlet</servlet-class>
    </servlet>

也就是说访问一个程序的时候,要实现的功能只能在doget()或者doPost()方法中写一坨,这样不利于解耦,于是我们就可以通过反射的方式去获取servlet类中的相应方法并执行来解决这个问题
看这个例子:

	@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决post请求中文乱码问题
        // 一定要在获取请求参数之前调用才有效
        req.setCharacterEncoding("UTF-8");
        // 解决响应的中文乱码
        resp.setContentType("text/html; charset=UTF-8");

        String action = req.getParameter("action");
        try {
            // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//            System.out.println(method);
            // 调用目标业务 方法
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);// 把异常抛给Filter过滤器
        }
    }

首先写一个抽象的servlet类,其余servlet类都继承该类,我们在重写HttpServlet类的方法的时候,获取参数中的关键字来判断最终使用该类的哪一个方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值