Java基础(四):java 反射机制

反射是什么

JAVA反射机制是在运行状态中,对于任意一个类,都可以获取这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象内容就称为java语言的反射机制。【翻译于 官方文档】html

反射的做用

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具备的成员变量和方法;
  • 在运行时调用任意一个对象的方法;

new和反射建立的区别

从结果来讲没有区别。java

new:静态编译,只能用于编译期就能肯定的类型,并且须要import相应的包。数组

反射:动态编译,在运行时能够肯定类型并建立其对象,可以实现一些更为动态的效果。bash

反射的实现

咱们知道,要使用一个类,就要先把它加载到虚拟机中,生成一个Class对象。这个class对象就保存了这个类的一切信息。 反射机制的实现,就是获取这个Class对象,经过Class对象去访问类、对象的元数据以及运行时的数据。有三种方法得到类的Class对象:spa

  • Class.forName(String className)
  • className.class
  • 实例对象.getClass()

什么是class类

在面向对象的世界里,万物皆对象。类是对象,类是java.lang.Class类的实例对象。另外class类只有java虚拟机才能new出来,任何一个类都是Class 类的实例对象,这实例对象有三种表达方式:翻译

public class Person {
}
复制代码
public class PersonClassTest {
    public static void main(String[] args) {
        try {
            Person p = new Person();
            //方式1
            Class p1 = Person.class;
            //方式2
            Class p2 = p.getClass();
            //方式3
            Class p3 = Class.forName("com.java.xiaoxin.Person");
            //能够经过类的类型建立该类的实例对象
            Person person = (Person) p1.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

反射涉及的API

反射首先获取Class对象;而后获取Method类和Field类;最后经过Method和Field类进行具体的方法调用或属性访问。code

1.在运行时获取对象所属类的类名等信息
对象名.getClass().getName();
复制代码
public class PersonClassTest {
    public static void main(String[] args) {
        String name = Person.class.getName();
        System.out.println(name);//com.java.xiaoxin.Person
    }
}
复制代码
2.在运行时,经过建立class对象,获取本身的父类信息
Class<?> clazz = Class.forName(当前类);
 Class<?> parentClass = clazz.getSuperclass();
 parentClass.getName();//得到父类名
复制代码
public class PersonClassTest {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.java.xiaoxin.Person");
            Class<?> parentClass = clazz.getSuperclass();
            parentClass.getName();
            System.out.println(parentClass.getName());//java.lang.Object
        }catch (Exception e){
			e.printStackTrace();
        }
    }
}
复制代码
3.经过反射机制建立一个类的对象
1:反射建立class对象
2:Classname 对象=classname.newInstance(参数);
复制代码
public class PersonClassTest {
    public static void main(String[] args) {
        try {
           Class clazz = Class.forName("com.java.xiaoxin.Person");
           Person person = (Person) clazz.newInstance();
        }catch (Exception e){
			e.printStackTrace();
        }
    }
}
复制代码
4.获取类的所有方法,存于一个数组中
//建立class对象
Class<?> clazz = Class.forName(ClassName);
// 返回声明的全部方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 
Method[] method1 = clazz.getDeclaredMethods();
//返回可被访问的公共方法 
Method[] method2 = clazz.getMethods();
复制代码
public class PersonClassTest {

    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.java.xiaoxin.Person");
            /** * 一个成员方法就是一个method对象 * getMethod()全部的 public方法,包括父类继承的 public * getDeclaredMethods()获取该类全部的方法,包括private ,但不包括继承的方法。 */
            Method[] methods = clazz.getMethods();//获取方法
            //获取因此的方法,包括private ,c.getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                //获得方法的返回类型
                Class returnType = methods[i].getReturnType();
                System.out.print(returnType.getName());
                //获得方法名:
                System.out.print(methods[i].getName() + "(");

                Class[] parameterTypes = methods[i].getParameterTypes();
                for (Class class1 : parameterTypes) {
                    System.out.print(class1.getName() + ",");
                }
                System.out.println(")");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

输出:htm

voidwait()
voidwait(long,int,)
voidwait(long,)
booleanequals(java.lang.Object,)
java.lang.StringtoString()
inthashCode()
java.lang.ClassgetClass()
voidnotify()
voidnotifyAll()
复制代码
5.获取类的所有字段,存于一个数组中
Class<?> clazz = Class.forName(classname);
// 取得本类已声明的全部字段,包括私有的、保护的
Field[] field = clazz.getDeclaredFields();
// 取得本类中可访问的全部公共字段
Field[] filed1 = clazz.getFields();
复制代码
public class Person {
   private String name;
   public int age;
}
复制代码
public class PersonClassTest {

    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.java.xiaoxin.Person");
            Field[] field = clazz.getDeclaredFields();
            Field[] filed1 = clazz.getFields();
            for(Field f:field){
                //获取成员变量的类型
                Class filedType=f.getType();
                System.out.println(filedType.getName()+"-->"+f.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

输出:对象

java.lang.String-->name
int-->age
复制代码
6.方法反射的操做

获取一个方法:须要获取方法的名称和方法的参数才能决定一个方法。blog

方法的反射操做:

method.invoke(对象,参数列表);
复制代码
public class Person {
    private String name;
    public int age;

    public void say(String name,int age){
        System.out.print(name+"今年"+age+"岁");
    }

}
复制代码
public class PersonClassTest {

    public static void main(String[] args) {
        try {
            Person person=new Person();
            Class clazz=person.getClass();
            Method method=clazz.getMethod("say",new Class[]{String.class,int.class});
            //也能够 Method method=c.getMethod("add",String.class,int.class);
            //方法的反射操做
            method.invoke(person,"小新",18);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

输出:

小新今年18岁
复制代码

参考资料

www.cnblogs.com/huangdabing…

www.fangzhipeng.com/javaintervi…

相关文章
相关标签/搜索