반성의 자바 기초

반성의 자바 기초

반성은 무엇입니까

  우선, 우리는 반성이 무엇인지 알 필요가있다. 즉, 내 자신의 이해가에 따라 원칙적으로 캡슐화 반영 자바 빈즈를 운영하는 것이 더 편리

자바 빈즈는 특별한 형식의 클래스 사양입니다 :

  1. 자바 빈즈 클래스는 키워드에게 공문 클래스를 사용하여 공용 클래스해야합니다.
  2. 자바 빈즈 클래스는 공공 인수가없는 생성자로 선언해야합니다.
  3. 자바 빈즈 클래스 인스턴스 변수는 모든 인스턴스 변수는 private 키워드를 사용하여 선언, 즉, 개인해야합니다.
  4. 우리는 자바 빈즈 클래스의 인스턴스 변수에 대한 공공 게터 / 세터 메소드를 제공해야합니다. (게터 / 세터 메소드에서는, 데이터 보안을 보장하기 위해, 정당성 등 일부 액세스 제어, 데이터 유효성 검사를 할 수 있습니다.)
  5. 자바 빈즈 클래스의 인스턴스는 이름 지정 규칙 속성 :

    1. 속성 이름 앞에 두 글자는 소문자 : 첫 번째 편지는 다음 getName /에서는 setName에 대한 게터 / setter 메소드는 재산이라는 이름으로 부품 / 세트를 얻을, 그것의 게터 / 세터 메소드로 사용되는 속성 이름을 대문자로.
    2. 게터 / 세터 방법으로서 직접 사용될 속성 이름 / 얻을 후방, 즉, 동일한 속성 이름 케이스 세트 : 제 대문자 속성 이름. uName의 이름 속성, getuName / setuName과의 게터 / 세터 메소드로.
    3. 속성 이름이 대문자 전 : 속성 이름을 직접 게터 / 세터 방법으로 사용 설정 / 후면 부분, 같은 속성 이름 케이스를 얻을. IDCODE이라는 속성, getIDcode / setIDcode과의 게터 / 세터 메소드로.
    4. 프로퍼티 이름은 대문자 : 게터 / 세터 방법 얻을 설정 / 후방으로 직접 사용되는 속성 명, 동일한 속성 이름 케이스. UCODE이라는 속성, getUcode / setUcode과의 게터 / 세터 메소드로. 그러나이 경우는, 속성을 찾을 수 없습니다 응용 프로그램에서 오류가 발생합니다 .

참조 기사

자기 반성을 사용하는 방법

내성적 기본 클래스 (인터페이스)이다 : Introspector(S) BeanInfo(인터페이스), PropertyDescriptor(S) java.bean 패키지 세있는.

Introspector내성적 입구 획득하는 데 사용되는 유틸리티 클래스입니다 BeanInfo자바 빈즈의 정보를.


시험 콩 : 학생

public class Student {
    private String name;
    private String address;

    public Student() {
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
//static BeanInfo getBeanInfo(Class<?> beanClass):在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件
BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);

빈 메시지를 취득 후에는 기술자의 모든 속성을 얻을 수 있습니다 :

PropertyDescriptor[] p = beanInfo.getPropertyDescriptors();

를 인쇄하고 결과를 볼 순회 :

BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);
PropertyDescriptor[] p = beanInfo.getPropertyDescriptors();
System.out.println(p.length);
for (PropertyDescriptor descriptor : p) {
    System.out.println(descriptor);
}

//输出--------------
p.length = 3
java.beans.PropertyDescriptor[name=address; propertyType=class java.lang.String; readMethod=public java.lang.String nei_xing.Student.getAddress(); writeMethod=public void nei_xing.Student.setAddress(java.lang.String)]
//为了方便观察加了注释隔开
java.beans.PropertyDescriptor[name=class; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]
//
java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String nei_xing.Student.getName(); writeMethod=public void nei_xing.Student.setName(java.lang.String)]

여기에, 학생의 특성 만이 있지만, 세 개의 개체 설명, 이유는

개체 그래서 모든 클래스 getClass () 메소드가, 모든 클래스는 Object에서 상속하기 때문에, Class 형 개체 자체의 객체를 얻을 수 getClass () 메소드를 선언합니다. 자기 반성을 사용하지만 클래스가 아닌 클래스 필드 (키워드 클래스, 클래스 이름이 아닙니다)가 아니라 setClass () 메소드, 그래서 일반적으로 프로그래밍 "클래스"를 필터링 할 필요가 속성
참조

해결 방법 :
사용 getBeanInfo(Class<?> beanClass)오버로드 방법 :
static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass):의 BeanInfo 얻을 브레이크 포인트 지정된 클래스,
예 :

BeanInfo beanInfo1 = Introspector.getBeanInfo(Student.class, Object.class);

이 경우 그 속성은 기술자는 두 학생 및 필터링 얻을 수있는 class특성을.

의의 게터 / 세터 방법을 얻을 설정할 수 있습니다 각 속성 기술자를 얻은 후 :

Student stu = new Student();
BeanInfo beanInfo1 = Introspector.getBeanInfo(Student.class, Object.class);
PropertyDescriptor[] p1 = beanInfo1.getPropertyDescriptors();
System.out.println(p1.length);
for (PropertyDescriptor d : p1) {
    String name = d.getName();
    System.out.println("name = " + name);
    Method getter = d.getReadMethod();//获取getter方法
    Method setter = d.getWriteMethod();//获取setter方法
    if ("name".equals(name)){
        setter.invoke(stu, "张三");//使用反射调用该方法
    }
    if ("address".equals(name)){
        setter.invoke(stu, "上海");
    }
    System.out.println(getter.invoke(stu));
}

출력 :

2
name = address
上海
name = name
张三

위는의 BeanInfo 객체를 제외하고 얻을 속성 기술자가 직접 설명 속성을 만들 수 있습니다 내성적 구현 한 것입니다 :

PropertyDescriptor pd = new PropertyDescriptor("address", Student.class);
Method getter = pd.getReadMethod();
Method setter = pd.getWriteMethod();

반성 데모에 두 개의 서블릿을 넣어 :


데모 1

프론트 페이지 :

<form action="/introspectorServlet" method="post">
    姓名 <input type="text" name="name" /> <br/>
    住址 <input type="text" name="address"/> <br/>
    <input type="submit" value="提交"/>
</form>

IntrospectorServlet :

@WebServlet("/introspectorServlet")
public class IntrospectorServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //处理请求乱码
        request.setCharacterEncoding("UTF-8");
        //获取页面提交的所有的数据
        /*
            map集合的key是form表单标签的name属性值
            map集合的value是浏览器输入框输入的值,以String类型的数组形式接收
            举例:
            住址 <input type="text" name="address"/> <br/>
            key:address
            value:{"上海"}
         */
        Map<String, String[]> m = request.getParameterMap();
//        System.out.println(m);
        //创建封装属性的目标对象person
        Person p = new Person();
        try {
            //调用方法
            setProperty(p,m);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(p.getName());
        System.out.println(p.getAddress());
    }

    private void setProperty(Object obj, Map<String, String[]> m) throws Exception {
        // 将请求参数中 map的key 与传入对象属性名称 比较,如果一致,将参数的值赋值给对象属性
        //使用内省类获取BeanInfo类的对象
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        //获取所有的属性描述器
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        //遍历数组取出每一个属性描述器
        for (PropertyDescriptor descriptor : propertyDescriptors) {
            //获取Person类中的属性
            String property_name = descriptor.getName();
            //判断属性在map中是否存在对应值
            if(m.containsKey(property_name)){
                //包含
                //获取对应的value值
                String value = m.get(property_name)[0];
                /*
                     Method getWriteMethod() 获得应该用于写入属性值的方法。
                 */
                Method setter = descriptor.getWriteMethod();
                //将value 写到属性中
                setter.invoke(obj, value);
            }
        }
    }
}

사용하여 request.getParameterMap();문자열을 프론트 데스크에서 얻은 데이터를하고 있습니다, 그럼 어떻게 현장에서 자바 빈즈의 기본 유형에 성찰에 데이터를 캡슐화 기술을 사용 하는가?


데모 1

학생 Bean 클래스

public class Person {
    private String name;
    private String address;
    private int age;
    private double money;


    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    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 String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

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

서블릿 코드 :

@WebServlet("/introspector2Servlet")
public class IntrospectorServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //处理中文乱码
        request.setCharacterEncoding("UTF-8");
        Person p = new Person();
        //获取所有的数据
        //key 标签 name属性值  value 输入的值
        Map<String, String[]> map = request.getParameterMap();
        try {
            setProperty(p, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(p.getName());
        System.out.println(p.getAddress());
        System.out.println(p.getAge());
        System.out.println(p.getMoney());
    }

    private void setProperty(Object obj, Map<String, String[]> map) throws Exception {
        //内省
        //获取所有的属性封装到BeanInfo对象中
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        //获取所有的属性描述器
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        //遍历
        for (PropertyDescriptor descriptor : propertyDescriptors) {
            //获取属性名
            String propertyName = descriptor.getName();
            //判断集合中是否包含当前属性名
            if (map.containsKey(propertyName)) {
                //包含
                //获取get方法
                Method getterMethod = descriptor.getReadMethod();
                //获取get方法返回值类型 String int double
                String returnTypeName = getterMethod.getReturnType().getSimpleName();

                //获取set方法
                Method setterMethod = descriptor.getWriteMethod();
                //获取mapvalue
                String value = map.get(propertyName)[0];//"18"
                //多分支语句
                switch (returnTypeName) {
                    case "int":
                        int age = Integer.parseInt(value);
                        //执行set方法
                        setterMethod.invoke(obj, age);
                        break;
                    case "double":
                        double v = Double.parseDouble(value);
                        //执行set方法
                        setterMethod.invoke(obj, v);
                        break;
                    case "float":
                        float v1 = Float.parseFloat(value);
                        //执行set方法
                        setterMethod.invoke(obj, v1);
                        break;
                    case "long":
                        long v2 = Long.parseLong(value);
                        //执行set方法
                        setterMethod.invoke(obj, v2);
                        break;
                    case "boolean":
                        boolean v3 = Boolean.parseBoolean(value);
                        //执行set方法
                        setterMethod.invoke(obj, v3);
                        break;
                    default:
                        //执行set方法
                        setterMethod.invoke(obj, value);
                        break;
                }
            }
        }
    }
}

도구를 BeanUtils

: 당신은 대부분의 시간을 당신이 아파치 도구를 사용할 수 있도록 직접, 몇 가지 복잡한있다 성찰 볼 수있다 org.apache.commons.beanutils.BeanUtils, (사용 가져올 필요 commons-beanutils-1.9.2.jar하고 commons-logging-1.1.1.jar두 개의 패키지) 받는다는 좌표 이것이다 :

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>

이 도구 클래스는 채우기 () 메소드가 있습니다 static populate(Object bean, Map<String,String[]> properties)에 String의 키의지도와 (자바 빈즈 패키지를 완료하기 위해 일치하는 속성 이름 또는 및 게터 / 세터 방법은 관련이 이름은, 적어도 스프링의 JdbcTemplate은이다 ) 속성 이름을 수정하지만 여전히 패키지를 완료 할 수 있습니다 게터 / 세터 메소드를 수정하지 않습니다

그런 다음 캡슐화는 코드의 라인을 완료 할 수 있습니다 :

BeanUtils.populate(new Student,request.getParameterMap());

추천

출처www.cnblogs.com/lixin-link/p/11222743.html