JAVA SE 基础复习-Class与反射(1)

Class

  关于Class,直接参考http://lavasoft.blog.51cto.com/62575/15433

  Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
      Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。 
      虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
      基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。 
      每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
      一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。

 
一、如何得到Class的对象呢?有三种方法可以的获取:
    1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如:
    MyObject x;
    Class c1 = x.getClass();
    2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如: 
    Class c2=Class.forName("MyObject"),Employee必须是接口或者类的名字。
    3、获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。例如
    Class cl1 = Manager.class;
    Class cl2 = int.class;
    Class cl3 = Double[].class;
    注意:Class对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的int.class是一个Class类型的对象。由于历史原因,数组类型的getName方法会返回奇怪的名字。
二、Class类的常用方法
    1、getName() 
    一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
    2、newInstance()
    Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:
    x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。
  假如没有无参构造器,会抛出InstantiationException错误。为什么在使用JSON库的时候要求有无参构造器,就是这个原因。
    3、getClassLoader() 
    返回该类的类加载器。
    4、getComponentType() 
    返回表示数组组件类型的 Class。
    5、getSuperclass() 
    返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
    6、isArray() 
    判定此 Class 对象是否表示一个数组类。
三、Class的一些使用技巧
    1、forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如
    Object obj = Class.forName(s).newInstance();
    2、虚拟机为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。例如:
    if(e.getClass() == Employee.class)...

反射

 1、介绍

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

  反射类在java.lang.reflect包中。常用到的有以下几个类

  java.lang.Class;                

  java.lang.reflect.Constructor; 

  java.lang.reflect.Field;        

  java.lang.reflect.Method;

  java.lang.reflect.Modifier;

2、具体功能实现

  1)反射机制获取类对象

    上面已经提到三种方式。

  2)创建对象

    Father father=(Father)cls.newInstance();//假如没有无参构造器,则会抛出InstantiationException

  3)获取属性

public class Father {
    public static int cnt=0;
    private int age;
    public String name;
    public Father()
    {}
    public Father(int age)
    {
        this.age=age;
    }
}
    public static void main(String[] args) {
        try {
            Class<?> cls=Class.forName("Father");
            Field[] fields=cls.getDeclaredFields();
            System.out.println(Arrays.toString(fields));
            Field[] fieldss=cls.getFields();
            System.out.println(Arrays.toString(fieldss));
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } 

输出

[public static int Father.cnt, private int Father.age, public java.lang.String Father.name]
[public static int Father.cnt, public java.lang.String Father.name]

getDeclaredFields()会输出全部属性,包括静态成员变量和普通成员变量

getFields()会输出全部public属性变量。

要获取某个具体的属性,可以使用getDeclaredFields(String)或者getFields(String).

    //获取类  
    Class c = Class.forName("User");  
    //获取id属性  
    Field idF = c.getDeclaredField("id");  
    //实例化这个类赋给o  
    Object o = c.newInstance();  
    //打破封装  
    idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
    //给o对象的id属性赋值"110"  
    idF.set(o, "110"); //set  
    //get  
    System.out.println(idF.get(o)); 

  4) 获取方法

        try {
            Class<?> cls=Class.forName("Father");
            Method[] methods=cls.getDeclaredMethods();
            System.out.println(Arrays.toString(methods));
            Method[] methodss=cls.getMethods();
            System.out.println(Arrays.toString(methodss));
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } 

输出

[public int Father.getAge(), public static int Father.getCnt(), private java.lang.String Father.getName()]
[public int Father.getAge(), public static int Father.getCnt(), public final native java.lang.Class java.lang.Object.getClass(), public native int java.lang.Object.hashCode(), public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll(), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException]

由上可知,getDeclaredMethods()获取该类的所有方法。getMethods()获取此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法

调用method的方法

  invoke(Object obj, Object... args) 
          对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

    getModifiers() 
          以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。

  5) 以前写的一个例子,从request中解析出对象

    /**
     * 填充类的全部属性,包括父类
     * @param cls
     * @param rs
     * @return
     */
    private static Object assignObjectForRequestISOPartly(Class cls,HttpServletRequest request,Map<String, String> map)
    {
        Class<?> demo=null;
           Object d=null;
        try{
        demo=cls;
        }catch(Exception e)
        {
            e.printStackTrace();
        }
        try{
        d=demo.newInstance();//通过类的实例来实例化对象
        }catch (InstantiationException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IllegalAccessException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        }
        Field[] f=getAllFields(demo);//获取属性
        for(int i=0;i<f.length;i++)
        {
            String typeName=f[i].getType().getName();
            String name=f[i].getName();
            if(!map.containsKey(name))
                continue;
            String value=request.getParameter(name);
            
            if(StringUtil.isNullOrEmpty(value))
                continue;
            DebugUtil.p(name+"     "+value);
            
            try{
                value=new String(value.getBytes("iso8859-1"), "UTF-8");
                DebugUtil.p(name+"     "+value);
            }catch(UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
            value=value.trim();//去掉空格或者换行符
            try{
                if(typeName.contains("String"))
                {
                    setter(d,upperFisrt(name) , value, f[i].getType());
                }
                else if(typeName.contains("int"))
                {
                    setter(d,upperFisrt(name) , Integer.parseInt(value), f[i].getType());
                }
                else if(typeName.contains("boolean"))
                {
                    is(d,upperFisrt(name) , Boolean.parseBoolean(value), f[i].getType());
                }
                else if(typeName.contains("float"))
                {
                    setter(d,upperFisrt(name) , Float.parseFloat(value), f[i].getType());
                }
                else if(typeName.contains("double"))
                {
                    setter(d,upperFisrt(name) ,Double.parseDouble(value), f[i].getType());
                }
                else
                {
                    setter(d,upperFisrt(name),assignObjectForRequest( f[i].getType(),request), f[i].getType());
                }
            }catch(Exception e){e.printStackTrace();}
        }
        return d;
    }

    /**
     * 获取所有的属性
     * @param object
     * @return
     */
    public static Field[] getAllFields(Class cls)
    {
        Class<?> cla=cls;
        ArrayList<Field> arrs=new ArrayList<Field>();
        for(;cla!=Object.class;cla=cla.getSuperclass())
        {
            Field[] fields=cla.getDeclaredFields();
            for(int i=0;i<fields.length;i++)
            {
                arrs.add(fields[i]);
            }
        }
        Field[] fields=new Field[arrs.size()];
        arrs.toArray(fields);
        return fields;
    }

    /** 
     * @param obj 
     *            操作的对象 
     * @param att 
     *            操作的属性 
     * @param value 
     *            设置的值 
     * @param type 
     *            参数的属性 
     * */
    public static void setter(Object obj, String att, Object value, 
            Class<?> type) { 
        try { 
            if(value!=null)
            {
                Method method = obj.getClass().getMethod("set" + att, type); //getMethod(name,objtype)返回指定公共成员方法
                method.setAccessible(true);
                method.invoke(obj, value);
            } 
        } catch (Exception e) { 
            //e.printStackTrace(); 
        } 
    }
原文地址:https://www.cnblogs.com/maydow/p/4803241.html