1.基础概念

  class类:

  1.1java是面向对象的,但是在java中存在两种东西不是面向对象的

    一种是普通的数据类型,这也是封装数据类存在的原因.

    二种是静态静态成员.

  1.2所以我们首先要理解,类也是一种对象,类是java.lang.Class类的对象.

  1.3反射的操作其实是执行了编译,获得了类的编译信息,也就是字节码.

  1.4获取类类型可以有三种方式:

DemoGetClassType.java
/**
* Created by garfield on 2016/10/11.
* 三种方式获得类类型
*/
public class DemoGetClassType {
public static void main(String[] args) {
//car是一个对象
Car car = new Car();
//那么既然Car类型为一个对象,那么如何表示Car这个类:
//查看Class源码发现类是有构造方法的,但是是私有的,只有java虚拟机才能创建Class实例,所以我们要通过其他方法来表示类对象
//类是Class的实例对象,称之为该类的类类型(class type) //可以有三种写法
//第一种:每一个类都有一个静态成员:class
Class c1 = Car.class; //第二种:利用getClass()方法
Class c2 = car.getClass(); //类类型是相等的
System.out.println(c1 == c2);
Class c3 = null;
try {
c3 = Class.forName("com.learn.reflect.a_GetClassType.Car");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c2 == c3); //通过类类型可以创建类实例,其实际是通过调用类的无参构造方法,
try {
Car car1 = (Car)c1.newInstance();
car1.run();
} catch (InstantiationException e) {
//如果丢失无参构造方法,抛出InstantiationException,也就是实例化异常
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
}
class Car { void run(){
System.out.println("i can run");
}
}

2.动态加载类

  2.1在类对象的forName()方法中,是可以表示动态加载类的,此处区分:

    一,在编译时刻加载的类是静态加载类

    二,运行时刻加载类是动态加载类

  2.2利用动态时刻加载可以避免一个功能出错的时候整个系统都不能运行

DemoStaticLoad.java
/**
* Created by garfield on 2016/10/13.
*/
public class DemoStaticLoad { public static void main(String[] args) {
//new创建对象 是静态加载类,在编译时刻就需要加载任何可能使用到的类
//这个类当中,由于都是new加载,所以当bus或者jeep有任何一个类不存在时,编译报错
//此时应当考虑使用动态加载,尤其是当类数量多的时候
if("bus".equals(args[0])){
Bus bus = new Bus();
bus.start();
}
if("jeep".equals(args[0])){
Jeep jeep = new Jeep();
jeep.start();
}
}
}

DemoDynasticLoad.java

/**
* Created by garfield on 2016/10/13.
*/
public class DemoDynasticLoad { public static void main(String[] args) {
try {
//动态加载类,在运行时刻编译,只有当运行类不存在时才会报错
//但凡这种多功能编程,都应该设计成这种不用非重新编译不可的结构
Class Wheel = Class.forName(args[0]);
Wheel wheel = (Wheel) Wheel.newInstance();
wheel.start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

3.获取类的信息

  3.1普通的数据类型以及void同样存在类类型

  3.2可以获取类的方法,成员变量,构造函数,包名,父类,接口等信息

DemoGetClassInformation.java
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; /**
* Created by garfield on 2016/10/13.
* 打印出关于输入类型的方法和参数,成员变量,构造函数
*/
public class DemoGetClassInformation {
public static void main(String[] args) {
printClassInformation("aa");
printClassInformation(11);
} static void printClassInformation(Object obj) {
Class objClass = obj.getClass();
System.out.println(objClass.getName());
//获取不带前缀的类名
System.out.println(objClass.getSimpleName());
/**
* 看源码可以看出,getMethods返回了所有的public方法,其中包括继承而来的方法
* 如果想获取本身的所有方法,用getDeclaredMethods()
*/
Method[] methods = objClass.getMethods(); for (Method method : methods) {
System.out.println("================================");
System.out.println("方法名称是" + method.getName());
System.out.println("返回值是:" + method.getReturnType().getName());
//获取参数列表,返回值是参数的类类型
Class[] params = method.getParameterTypes();
for (Class param : params) {
System.out.println("参数:" + param.getName());
}
}
/**
* java.lang.reflect.Field封装了成员变量
* 与方法相仿,getFields()获得的是public变量,如果要获取本身声明的私有变量,采用getDeclaredFields()
*/
System.out.println("=======打印成员变量=======");
Field[] fields = objClass.getDeclaredFields();
for (Field field : fields) {
System.out.println("成员变量类型:" + field.getType().getName() + ", 成员变量名" + field.getName());
} /**
* java.lang.Constructor封装构造函数
* 与上述相仿,getConstructors()得到public构造函数,getDeclaredConstructors()获得声明构造函数
*/
System.out.println("=======打印构造函数=======");
Constructor[] constructors = objClass.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("构造函数名" + constructor.getName());
Class[] conParas = constructor.getParameterTypes();
for (Class conPara : conParas) {
System.out.println("参数:" + conPara.getName());
} }
}
}

4.方法的反射

  4.1需要理解方法反射的操作 method.invoke(对象,参数列表)

  4.2调用方法是传入的是实例和参数

DemoMethodReflection.java
/**
* Created by garfield on 2016/10/13.
* 方法反射实例
*/
public class DemoMethodReflection {
public static void main(String[] args) {
//先得到类信息
MathCount mathCount = new MathCount();
Class mathCountClass = mathCount.getClass();
try {
/**
* 获得方法,然后进行方法反射,如果有返回值可以获得返回值
* 注意可变参数两种写法
* 1.new class[]{int.class,int.class}
* 2.int.class,int.class
*/
Method method = mathCountClass.getMethod("add",new Class[]{int.class,int.class});
method.invoke(mathCount,new Object[]{22,44});
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} } }
class MathCount { public void add(int a, int b){
System.out.println(a + b);
}
}

5.集合的本质有助于我们理解方法反射和正常调用的不同(反射时绕过了编译)

  5.1集合中通过反射可以放入不同类型的元素

  5.2不同泛型的集合,其本质是同一个类类型

DemoSetNature.java

/**
* Created by garfield on 2016/10/13.
*/
public class DemoSetNature {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
ArrayList<String> arrayList1 = new ArrayList<String>();
Class arrayListClass = arrayList.getClass();
Class arrayList1Class = arrayList1.getClass();
System.out.println(arrayList1Class == arrayListClass);
/**
* 结果为true说明,编译之后集合的泛型是去泛型化的
* 泛型只在编译阶段有效
*/
try {
Method method = arrayListClass.getMethod("add",Object.class);
//!绕过编译之后可以添加其他类型的数据
method.invoke(arrayList1,200);
System.out.println(arrayList1);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

由浅到深理解java反射的更多相关文章

  1. 深入理解Java反射+动态代理

    答:   反射机制的定义: 是在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为j ...

  2. 理解Java反射机制

    理解Java反射机制 转载请注明出处,谢谢! 一.Java反射简介 什么是反射? Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在.灵活掌握Java反射机制,对学习框架技术有很大 ...

  3. 由浅入深理解----java反射技术

    java反射机制详解 java反射机制是在运行状态下,对任意一个类可以获取该类的属性和方法,对任意一个对象可以调用其属性和方法.这种动态的获取信息和调用对象的方法的功能称为java的反射机制 clas ...

  4. 理解Java反射

    一.反射简介 Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息:另一种是反射机制,它允许我们在运行时发现和使用类的信息. 1. ...

  5. 深入理解Java反射

    要想理解反射的原理,首先要了解什么是类型信息.Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息:另一种是反射机制,它允许我们在 ...

  6. Java复习总结——详细理解Java反射机制

    反射是什么 反射的作用用一句简单的话来讲就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少. 能够分析类能力的 ...

  7. 如何理解java反射?

    一.反射基本概念 反射之中包含了一个"反"的概念,所以要想解释反射就必须先从"正"开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产 ...

  8. 由浅到深理解ROS(1)

    ROS机器人操作系统 ( Robot Operating System 或简称 ROS),可以帮助提高机器人软件的开发效率.ROS能够提供类似传统操作系统的诸多功能,如硬件抽象.底层设备控制.常用功能 ...

  9. JavaScript基础知识从浅入深理解(一)

    JavaScript的简介 javascript是一门动态弱类型的解释型编程语言,增强页面动态效果,实现页面与用户之间的实时动态的交互. javascript是由三部分组成:ECMAScript.DO ...

随机推荐

  1. javascript动画:velocity.js学习

    第二章:基础知识 一.velocity和jQuery: Velocity函数是独立于jQuery的,但两者可以结合使用.通常这么做的好处是可以利用jQuery的链式操作:当你先用jQuery选择了一个 ...

  2. qt 汉化 国际化

    两种方法. 1. 使用 QTextCodec  setcodeforname 设置编码, 然后在程序中对于需要处理的字符使用 fromLocal8Bit . 2. 使用 Linguist. 首先把文件 ...

  3. Linux随笔(安装ftp,安装jdk,安装 tomcat,安装redis,安装MySQL)

    su: authentication failure 解决办法:sudo passwd root  更改密码即可 确认虚拟机用到的联网方式是桥接模式,不然Windows是ping不通Linux的,确保 ...

  4. Markdown转pdf

    最近由于项目需要,要用到把markdown转换成pdf文件下载下来,最开始的时候想到的是先把markdown转成html,用到的是Parsedown:然后再将html转成pdf,用到了html2pdf ...

  5. Django中Admin样式定制

    Django自带的admin在展示数据是样式有点单一,我们可以自己定义数据的展示样式. 一.自定义数据展示样式 1.后台查询书记列表时,同时列出出版社和出版时间: admin.py文件 from dj ...

  6. Linux系统英文切换中文

    Centos系统作为开源最优秀的Linux版本,很多时候作为服务器使用.由于很多linux初学者不太习惯字符界面操作.一般都会安装图形界面,可是安装之后发现是英文的怎么设置让系统显示为中文呢?咗嚛本经 ...

  7. 在线用户管理--ESFramework 4.0 进阶(05)

    无论我们采用何种通信框架来构建我们的分布式系统,在服务端进行用户管理都是非常重要的一个环节.然而用户管理是否应该隶属于通信框架了?这个并不一定,通常来说,用户管理是与具体应用紧密相关的,应该是由应用解 ...

  8. Spark 倾斜连接

    [数据倾斜出现的原因] 并行计算中,我们总希望分配的每一个任务(task)都能以相似的粒度来切分,且完成时间相差不大.但是由于集群中的硬件和应用的类型不同.切分的数据大小不一,总会导致部分任务极大地拖 ...

  9. vc中主线程等待子线程退出的方法

    VC线程同步,在子线程中等待另一子线程结束,通过WaitForSingleObject可以实现,但是如果在主线程中等待子线程结束,这个函数是无法完成要求的,因为它会造成主线程挂起,导致程序死掉.我们可 ...

  10. chapter 13_1 算术类的元方法

    假设用table来表示集合,用function去计算集合的交集.并集. 为了保持名称空间的整齐,将这些函数存入一个名为Set的table中. 现在,假设用“+”来计算两个集合的并集,那么就要让所有用于 ...