Java基础入门之反射

今天学到Java基础中的反反射。依照我学习后的个人理解呢,反射就是一套获取类、属性、方法等的工具吧。(其实,感觉学完反射后,有点像喝凉水,解渴但确实我也没体会出它有什么味道,我可能没有学到精髓吧。自己都能感觉少点什么。这是我Java基础学习的最后一个部分了,我想再复习一遍,然后再学习其他的。也想有时间看看JVM和计算机系统之类的书。总觉得自己不是科班出身,思路上有些短板。要继续努力咯。)

在学习反射之前,我先回忆了一下可变参数。

public static void main(String[] args) {            test();//调用方法1test("JAVA");//调用方法2test("JAVA","工程师");//调用方法3test(new String[]{"水果","电器"});//调用方法4        }    static void test(String ... array){  //直接打印:System.out.println(array);for(String str:array){  //利用增强for遍历            System.out.println(str);            }        }

之所以回忆可变参数呢,是因为它与反射的应用有点像。如果将一个方法定义为可变参数,在调用的时候传参的限制就少了一大截。在反射当中呢,我们利用一些方法,得到类的实例对象,那么类里面的方法、属性等,就尽收眼底。在前面的学习中知道了,方法、属性等都有静态的和非静态的,私有的和非私有的之分,那么我们在调用的时候,想取哪一块,或者说只想取得哪一块,是不是也可以想个办法实现呢?这时候,反射就出现了,现今我对它的理解就只有这些了。继续努力吧。

一、反射的概念

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

Java反射机制主要提供了以下功能:

— 在运行时判断任意一个对象所属的类;

— 在运行时构造任意一个类的对象;

— 在运行时判断任意一个类所具有的成员变量和方法;

— 在运行时调用任意一个对象的方法;

— 生成动态代理。

JDK中,与反射相关的类,主要有以下几个

//java.lang包下

Class 类

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double) 和关键字 void 也表示为 Class 对象。

关于Class类JDK里面的解释:

public finalclass Class<T> implements java.io.Serializable,                              java.lang.reflect.GenericDeclaration,                              java.lang.reflect.Type,                              java.lang.reflect.AnnotatedElement {private static final int ANNOTATION= 0x00002000;private static final int ENUM      = 0x00004000;private static final int SYNTHETIC = 0x00001000;private static native void registerNatives();static {        registerNatives();    }/* * Constructor. Only the Java Virtual Machine creates Class     * objects.     */private Class() {}

Class类JDK里的一些方法(个人觉得读起来很舒服,自己想记录一下)

public String toString() {return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))+ getName();    }//应该是三元表达式

public static Class<?> forName(String className)throws ClassNotFoundException {        Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);    }

public static Class<?> forName(String name, boolean initialize,                                   ClassLoader loader)throws ClassNotFoundException    {        Class<?> caller = null;        SecurityManager sm = System.getSecurityManager();if (sm != null) {// Reflective call to get caller class is only needed if a security manager// is present.  Avoid the overhead of making this call otherwise.caller = Reflection.getCallerClass();if (loader == null) {                ClassLoader ccl = ClassLoader.getClassLoader(caller);if (ccl != null) {                    sm.checkPermission(                        SecurityConstants.GET_CLASSLOADER_PERMISSION);                }            }        }return forName0(name, initialize, loader, caller);    }

private static native Class<?> forName0(String name, boolean initialize,                                            ClassLoader loader,                                            Class<?> caller)throws ClassNotFoundException;

public T newInstance()throws InstantiationException, IllegalAccessException    {if (System.getSecurityManager() != null) {            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);        }// NOTE: the following code may not be strictly correct under// the current Java memory model.// Constructor lookupif (cachedConstructor == null) {if (this == Class.class) {throw new IllegalAccessException("Can not call newInstance() on the Class for java.lang.Class");            }try {                Class<?>[] empty = {};final Constructor<T> c = getConstructor0(empty, Member.DECLARED);// Disable accessibility checks on the constructor// since we have to do the security check here anyway// (the stack depth is wrong for the Constructor's// security check to work)                java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {public Void run() {                                c.setAccessible(true);return null;                            }                        });                cachedConstructor = c;            } catch (NoSuchMethodException e) {throw new InstantiationException(getName());            }        }        Constructor<T> tmpConstructor = cachedConstructor;// Security check (same as in java.lang.reflect.Constructor)int modifiers = tmpConstructor.getModifiers();if (!Reflection.quickCheckMemberAccess(this, modifiers)) {            Class<?> caller = Reflection.getCallerClass();if (newInstanceCallerCache != caller) {                Reflection.ensureMemberAccess(caller, this, null, modifiers);                newInstanceCallerCache = caller;            }        }// Run constructortry {return tmpConstructor.newInstance((Object[])null);        } catch (InvocationTargetException e) {            Unsafe.getUnsafe().throwException(e.getTargetException());// Not reachedreturn null;        }    }

public String getName() {        String name = this.name;if (name == null)this.name = name = getName0();return name;    }

// cache the name to reduce the number of calls into the VMprivate transient String name;private native String getName0();

还有很多,暂不记录了。。。。。

//java.lang.reflect  包下Constructor 代表构造函数Method 代表方法Field 代表字段Array 与数组相关

二、Class类的说明

常用的得到Class类的方法 // Class c=new Class(); 不可以,因为它被私有化了1) Class c=Student.class;   //用类名.class 就可以得到Class类的实例2) Student stu=new Student();Class c=stu.getClass();   //用对象名.getClass();3) Class c=Class.forName("com.mysql.jdbc.Driver");

//例一  通过调用无参的构造函数,创建类对象public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException {    Class clazz=Dog.class;    Dog dog=(Dog)clazz.newInstance();    dog.shout();    }}            class Dog{void shout(){    System.out.println("汪汪");    }}

通过例一,我并没有看出来利用反射的好处,呃~~

//例二 上例的改写Class clazz=Class.forName("com.weiboo.Dog"); //注意,必须是类的全部Dog dog=(Dog)clazz.newInstance();dog.shout();

//例三  (运行本类,Dog 和 Cat 类,必须有一个无参的构造函数)public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {    Dog dog=(Dog)createObj(Dog.class);    dog.shout();                    Cat cat=(Cat)createObj(Cat.class);    cat.speak();    }                    static Object createObj(Class clazz) throws InstantiationException, IllegalAccessException{return clazz.newInstance();  //调用的是newInstance() 方法创建的类对象,它调用的是类中无参的构造方法}    }        class Dog{void shout(){    System.out.println("汪汪");    }}        class  Cat{void speak(){    System.out.println("喵~~~");            }}

三、反射中的其他的类的说明

1) Constructor

代表类中的构造函数 Class 类提供了以下四个方法

public Constructor<?>[] getConstructors() //返回类中所有的public构造器集合,默认构造器的下标为0

public Constructor<T> getConstructor(Class<?>… parameterTypes) //返回指定public构造器,参数为构造器参数类型集合

public Constructor<?>[] getDeclaredConstructors() //返回类中所有的构造器,包括私有的

public Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes) //返回任意指定的构造器,包括私有的

import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;//例子 得到某个类中指定的某个构造函数所对应的 Constructor对象class Test2 {public static void main(String[] args) throws InstantiationException,            IllegalAccessException, ClassNotFoundException,            NoSuchMethodException, SecurityException, IllegalArgumentException,            InvocationTargetException {        Class<Cat> clazz = Cat.class;        Constructor<Cat> c = clazz.getConstructor(int.class, String.class);        Cat cat = (Cat) c.newInstance(20, "加飞猫");        cat.speak();    }class Cat {private String name;private int age;public Cat(int age, String name) {this.age = age;this.name = name;        }public Cat(String content) {            System.out.println("这是构造函数得到的参数" + content);        }void speak() {            System.out.println("喵~~~");            System.out.println("我的名字是" + this.name + "我的年龄是" + this.age);        }    }}

/例子 访问类中的私有构造函数Class clazz=Cat.class;Constructor c=clazz.getDeclaredConstructor();c.setAccessible(true);  //让私有成员可以对外访问Cat cat=(Cat) c.newInstance();  //对于私有的来说,能不能行?cat.speak();

2) Method 代表类中的方法

Class 类提供了以下四个方法

public Method[] getMethods() //获取所有的共有方法的集合,包扩继承的

public Method getMethod(String name,Class<?>… parameterTypes) // 获取指定公有方法 参数1:方法名 参数2:参数类型集合

public Method[] getDeclaredMethods() //获取所有的方法(包扩私有的),除了继承来的

public Method getDeclaredMethod(String name,Class<?>… parameterTypes) //获取任意指定方法,除来了继承来的

//调用类中的私有方法main 函数Class  clazz=Cat.class;//调用一个不带参数的方法Method m=clazz.getDeclaredMethod("speak");m.setAccessible(true);Cat c=new Cat();m.invoke(c);  //让方法执行                                    //调用一个带参数的方法Method m=clazz.getDeclaredMethod("eat", int.class,String.class);m.setAccessible(true);Cat c=new Cat();m.invoke(c, 20,"鱼");    class  Cat{private String name;private int age;                        Cat(){    }public Cat(int age,String name){this.age=age;this. name=name;    }                        public Cat(String content){    System.out.println("这是构造函数得到的参数"+content);    }                        private void speak(){    System.out.println("喵~~~");            System.out.println("我的名字是"+this.name+"我的年龄是"+this.age);    }                        private void eat(int time,String something){    System.out.println("我在"+time +"分钟内吃了一个"+something);    }}

例子 查看一个类中的所有的方法名public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {    Class  clazz=Cat.class;                        /*Method []  methodList=clazz.getMethods() ; //查看所有的公有方法,包扩继承的    for(Method m:methodList){    System.out.println(m.getName());    }*/Method []  methodList=clazz.getDeclaredMethods(); //查看所有的方法,包扩私有的,但不包扩继承的for(Method m:methodList){    System.out.println(m.getName());    }}

3) Field 代表字段

public Field getDeclaredField(String name) // 获取任意指定名字的成员

public Field[] getDeclaredFields() // 获取所有的成员变量,除了继承来的

public Field getField(String name) // 获取任意public成员变量,包含继承来的

public Field[] getFields() // 获取所有的public成员变量

//例子 访问字段public class Test {public static void main(String[] args) throws Exception {    Class clazz=Cat.class;                         /* Field field= clazz.getField("home");    Cat c=new Cat();    Object obj=field.get(c);    System.out.println(obj); // 家*/     Cat cat=new Cat();    Field  [] fieldList= clazz.getDeclaredFields();for(Field f:fieldList){  //访问所有字段f.setAccessible(true);    System.out.println(f.get(cat));                                    }        }}                            class  Cat{private String name="黑猫";private int age=2;public String home="家";}

四、反射的应用

用一个例子来说明一下,比较两个同类对象中的所有字段,不同的并把它输出来。

import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class Test {public static void main(String[] args) throws Exception {        Student stu1 = new Student(24, "李磊", "工程大学", "女");        Student stu2 = new Student(20, "王一", "师大", "男");        Map<String, String> map = compare(stu1, stu2);for (Map.Entry<String, String> item : map.entrySet()) {            System.out.println(item.getKey() + ":" + item.getValue());        }    }static Map<String, String> compare(Student stu1, Student stu2) {        Map<String, String> resultMap = new HashMap<String, String>();        Field[] fieldLis = stu1.getClass().getDeclaredFields(); // 得到stu1所有的字段对象try {for (Field f : fieldLis) {                f.setAccessible(true); // 别忘了,让私有成员可以对外访问Object v1 = f.get(stu1);                Object v2 = f.get(stu2);if (!(v1.equals(v2))) {                    resultMap.put(f.getName(), "stu1的值是" + v1 + "   stu2的值是"                            + v2);                }            }        } catch (Exception ex) {            ex.printStackTrace();        }return resultMap;    }}class Student {private String name;private String school;private String sex;public Student(int age, String name, String school, String sex) {this.age = age;this.name = name;this.school = school;this.sex = sex;    }private int age;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 getSchool() {return school;    }public void setSchool(String school) {this.school = school;    }public String getSex() {return sex;    }public void setSex(String sex) {this.sex = sex;    }}

以上就是Java基础入门之反射的详细内容,更多请关注其它相关文章!

往往教导我们大家要好好学习天天向上,

Java基础入门之反射

相关文章:

你感兴趣的文章:

标签云: