反射?看一篇文章你就会了

反射的概念反射的引入:
Object obj = new Student();
若程序运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象运行类型的方法:
1.若编译和运行类型都知道,使用 instanceof判断后,强转 。
2.编译时根本无法预知该对象属于什么类,程序只能依靠运行时信息来发现对象的真实信息,这时就必须使用反射了 。
3.要是想得到对象真正的类型,就得使用反射 。
什么是反射机制?
简单的来说,反射机制指的是程序在运行时能够获取自身的信息 。在JAVA中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息 。
反射机制的优点与缺点:
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念
静态编译:在编译时确定类型,绑定对象,即通过 。
动态编译:运行时确定类型,绑定对象 。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性 。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发 。
它的缺点是对性能有影响 。
使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求 。这类操作总是慢于只直接执行相同的操作 。
Class类和Class类实例
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类就是Class类 。
对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?
人 ? Person
Java类 ? Class
对比提问: Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个实例对象又分别对应什么呢?
对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等;
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的;

反射?看一篇文章你就会了

文章插图
 
用类来描述对象,类:描述数据的结构
用元数据来描述Class,MetaData(元数据):描述数据结构的结构;
反射就是得到元数据的行为;
备注:一个类在虚拟机中只有一份字节码;
获得Class对象如何得到各个字节码对应的实例对象?
每个类被加载后,系统会为该类生成对应的Class对象,通过Class对象可以访问到JVM中的这个类,
3种方式:
1、调用某个类的class属性获取Class对象,如Date.class会返回Date类对应的Class对象(其实就是得到一个类的一份字节码文件);
2、使用Class类的forName(String className)静态方法,className表示全限定名;如String的全限定名:java.lang.String;
3、调用某个对象的getClass()方法 。该方法属于Object类;
Class<?> clz = new Date().getClass();
public class ClassDemo1 {public static void main(String[] args) throws Exception {//获得Class对象的方法(三种)//一:调用属性Class<String> c = String.class;System.out.println(c);//打印结果:class java.lang.String String.class就表示JVM中一份表示String类的字节码Class<String> c2 = String.class;System.out.println(c == c2);//true都是String类的字节码 一个类在虚拟机中只有一份字节码;//二:使用forName()方法//Class cla = Class.forName("String");//ERROR,Class<String> cla = (Class<String>)Class.forName("java.lang.String");//必须用上全限定名,否则报错System.out.println(c == cla);//true//三:利用对象调用Object的getClass方法;Class c3 = new String().getClass();System.out.println(c == c3);//ture} }我的总结:获取Class对象最常用的是利用属性的方法!
九个预定义Class对象基本的 Java 类型(boolean、byte、char、short、int、long、float 、double)和关键字void通过class属性也表示为 Class 对象;
Class类中boolean isPrimitive() :判定指定的 Class 对象是否表示一个基本类型 。
包装类和Void类的静态TYPE字段;
Integer.TYPE == int.class ;
Integer.class == int.class;
数组类型的Class实例对象:
Class<String[]> clz = String[].class;
数组的Class对象如何比较是否相等? 数组的维数和数组的类型;
Class类中 boolean isArray() :判定此 Class 对象是否表示一个数组类型 。
public class PreClassDemo2 { public static void main(String[] args) { Class<?> in = int.class; System.out.println(in);//int Class<?> in2 = Integer.class; //包装类都有一个常量TYPE,用来表示其基本数据类型的字节码 Class<?> in3 = Integer.TYPE; System.out.println(in2);//class java.lang.IntegerSystem.out.println(in3);//intSystem.out.println(in3 == in);//true 包装类都有一个常量TYPE,用来表示其基本数据类型的字节码,所以这里会相等!System.out.println(in3 == in2);//falseClass<String[]> s = String [].class;Class<int[]> i = int [].class;//System.out.println(i ==s);//编译根本就通过不了,一个是int,一个是String}//这两个自定义的方法是可以的,一个int,一个Integer//包装类与基本数据类型的字节码是不一样的 public void show(int i){} public void show(Integer i){} }


推荐阅读