J2EE—反射

1. 什么是反射
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法

student.java
sid;
name;

User.java
uid;
name;

.....
java.lang.Class
java.lang.reflect.Field
java.lang.reflect.Method
java.lang.reflect.construct
类实例 Student.java User.java ...

2. 类类
所有狗 狗类 Dog 狗对象 旺财

所有猫 猫类 Cat 猫对象 肥波

所有类 类类 java.lang.Class 类对象 特定类


3. 一切反射相关的代码都从获得类(java.lang.Class)对象开始
3.1 Class.forName(完整类名)
3.2 类名.class
3.3 对象.getClass()


注1:ClassNotFoundException(类名错|少jar包)
注2:同一类的、类对象只会创建一个


4. 反射三大作用(java.lang.reflect.*)
4.1 实例化对象
c.newInstance()

Constructor.getConstructor/Constructor.getDeclaredConstructor
注:一定要提供无参构造器


4.2 动态调用方法
Method m;
m.invoke


4.3 读写属性
Field set/get


5. 访问修饰符
getModifiers()
private
protected
static
final
.....
反射怎么知道成员是被哪些修饰符所修饰的呢?


实体类Student.java

package
com.huangyucan.reflect; public class Student { private String sid; private String sname; public Integer age; static{ System.out.println("加载进jvm中!"); } public Student() { super(); System.out.println("调用无参构造方法创建了一个学生对象"); } public Student(String sid) { super(); this.sid = sid; System.out.println("调用带一个参数的构造方法创建了一个学生对象"); } public Student(String sid, String sname) { super(); this.sid = sid; this.sname = sname; System.out.println("调用带二个参数的构造方法创建了一个学生对象"); } @SuppressWarnings("unused") private Student(Integer age) { System.out.println("调用Student类私有的构造方法创建一个学生对象"); this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public void hello() { System.out.println("你好!我是" + this.sname); } public void hello(String name) { System.out.println(name + "你好!我是" + this.sname); } @SuppressWarnings("unused") private Integer add(Integer a, Integer b) { return new Integer(a.intValue() + b.intValue()); } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]"; } }
1、类类Class的类对象获取方式Demo1.java

package com.huangyucan.reflect;

/**
* 如何获取类对象(三种方式)
* 1、Class.forName("类的全路径") jdbc、自定义mvc框架
* 2、类的.class 做通用的查询
* 3、类实例.getClass() 做通用的增删改
* @author Admin
*
*/
public class Demo1 {

public static void main(String[] args) throws ClassNotFoundException {
// Class<?> clz=Class.forName("com.huangyucan.reflect.Student");
// Class<?> clz=Student.class;
Student stu=new Student();
Class<?> clz=stu.getClass();
System.out.println(clz);


}

/**
* 为什么jdbc连接要使用Class.forName("com.jdbc.mysql.Driver");
* 无论是mysql的驱动Driver还是Oracle的驱动.....;它必然需要实现jdbc的一个驱动接口;
* com.jdbc.mysql.Driver extends java.sql.Driver
* java.sql.Driver d=Class.forName("com.jdbc.mysql.Driver")
*
*
* web.xml
* <servlet>
* <servlet-name>xxx<servlet-name>
* <servlet-class>com.huangyucan.XxxServlet</servlet-class>
* </servlet>
*...
*
*com.huangyucan.XxxServlet extends httpServlet
*Class<?> clz=Class.forName("com.huangyucan.XxxServlet");
*httpServlet httservlet=clz.newInstanse();
*
*XxxServlet实例
* new XxxServlet();
*/

}


2、通过反射进行实例化Demo2.java
package com.huangyucan.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * 1、能够实例化未知的类
 * 2、能够通过私有构造器创造实例
 * @author Admin
 *
 */ 
public class Demo2 {

    public static void main(String[] args) throws Exception {
        Class clz=Student.class;
//        反射调用无参构造方法创建了一个学生对象
//        Student stu= (Student) clz.newInstance();
//        要拿到构造器类
//        Constructor con=clz.getConstructor(String.class);
//        通过构造器实例化对象
//        Object newInstance=con.newInstance("s001");
        
//        调用带二个参数的构造方法创建了一个学生对象
//        Constructor con=clz.getConstructor(String.class,String.class);
//    //    通过构造器实例化对象
//        Student stu=(Student)con.newInstance("s001","zs");
         
//        java.lang.NoSuchMethodException
//        (getConstructor只能找到public修饰的构造器,getDeclaredConstructor可以寻找到任何修饰符)
//        Constructor con=clz.getConstructor(Integer.class);
        Constructor con=clz.getDeclaredConstructor(Integer.class);
        con.setAccessible(true);
//        通过构造器实例化对象
        Student stu=(Student)con.newInstance(12);
        System.out.println(stu);
    }
    
}

3、反射调用方法Demo3.java
package com.huangyucan.reflect;

import java.lang.reflect.Method;

/**
 * 反射调用方法
 * AddOrderServlet
 * DelOrderServlet
 * 
 * -->OrderServlet
 * jsp-->methodName
 * dopost
 * String methodName=req.getParameter("methodName");
 * if("add".equals(methodName)){
 * 
 * }else if("del".equals(methodName)){
 *         del(req,resp);
 * }
 *
 *--->
 *del(req,resp);
 *add(req,resp);
 *
 * @author Admin
 */
public class Demo3 {

    public static void main(String[] args)throws Exception{
    
        Student stu=new Student();
//        stu..hello();
        Class clz=stu.getClass();
//        Method m=clz.getDeclaredMethod("hello");
//        m.invoke(stu);
        
        Method m=clz.getDeclaredMethod("hello",String.class);
        System.out.println(m.invoke(stu,"zs"));
        
//        Method m=clz.getDeclaredMethod("add",Integer.class,Integer.class);
//        m.setAccessible(true);
//        invoke:如果反射动态调用的方法是被void所修饰,那么返回的就是null
//        如果反射动态调用的方法是不被void所修饰,那么返回的就是被调用的方法的返回值
//        Object invoke=m.invoke(stu, 20,5);
//        System.out.println(invoke);
        
        
    }
    
}

4、反射读写属性Demo4.java

package
com.huangyucan.reflect; import java.lang.reflect.Field; /** * 反射属性赋值取值 * jsp * -->uname,sex,age,password,phone,address.... * servlet * String name=req.getParameter("uname"); * String sex=req.getParameter("sex"); * .... * User u=new User(); * u.setName(uname); * u.setSex(sex); *.... * * --> * 反射能过将jsp传递过来的参数直接封装到实体类中 * * @author Admin * */ public class Demo4 { public static void main(String[] args) throws Exception{ Student stu=new Student("s002","ls"); // stu.setSid("s001"); stu.age=22; // System.out.println(stu); Class clz=stu.getClass(); // Field field=clz.getDeclaredField("sid"); // field.setAccessible(true); // field.set(stu, "s002"); // System.out.println(stu); Field[] fields=clz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); System.out.println(field.getName()+":"+field.get(stu)); } } }





原文地址:https://www.cnblogs.com/bf6rc9qu/p/11024767.html