由浅到深理解java反射
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反射的更多相关文章
- 深入理解Java反射+动态代理
答: 反射机制的定义: 是在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为j ...
- 理解Java反射机制
理解Java反射机制 转载请注明出处,谢谢! 一.Java反射简介 什么是反射? Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在.灵活掌握Java反射机制,对学习框架技术有很大 ...
- 由浅入深理解----java反射技术
java反射机制详解 java反射机制是在运行状态下,对任意一个类可以获取该类的属性和方法,对任意一个对象可以调用其属性和方法.这种动态的获取信息和调用对象的方法的功能称为java的反射机制 clas ...
- 理解Java反射
一.反射简介 Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息:另一种是反射机制,它允许我们在运行时发现和使用类的信息. 1. ...
- 深入理解Java反射
要想理解反射的原理,首先要了解什么是类型信息.Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息:另一种是反射机制,它允许我们在 ...
- Java复习总结——详细理解Java反射机制
反射是什么 反射的作用用一句简单的话来讲就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少. 能够分析类能力的 ...
- 如何理解java反射?
一.反射基本概念 反射之中包含了一个"反"的概念,所以要想解释反射就必须先从"正"开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产 ...
- 由浅到深理解ROS(1)
ROS机器人操作系统 ( Robot Operating System 或简称 ROS),可以帮助提高机器人软件的开发效率.ROS能够提供类似传统操作系统的诸多功能,如硬件抽象.底层设备控制.常用功能 ...
- JavaScript基础知识从浅入深理解(一)
JavaScript的简介 javascript是一门动态弱类型的解释型编程语言,增强页面动态效果,实现页面与用户之间的实时动态的交互. javascript是由三部分组成:ECMAScript.DO ...
随机推荐
- HDU 1564 Play a game
Description New Year is Coming! ailyanlu is very happy today! and he is playing a chessboard game wi ...
- tomcat bio nio apr 模式性能测试
转自:tomcat bio nio apr 模式性能测试与个人看法 11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.a ...
- ubuntu显卡驱动安装及设置
转自: Ubuntu 14.04 Nvidia显卡驱动安装及设置 更换主板修复grub 引导后,无法从Nvidia进入系统(光标闪烁), 可能是显卡驱动出了问题. 1. 进入BIOS设置, 从集成 ...
- 在Wamp 添加站点和域名
在httpd.conf中使Include conf/extra/httpd-vhosts.conf生效 在conf/extra/httpd-vhosts.conf中加入如下代码 <Virtual ...
- deepin2014.1快捷键
初试deepin2014.1,发现windows很多快捷键在deepin中也完美支持,举例如下: ctrl+shift+n : 新建文件夹 窗口键+E:打开文件系统 窗口键+TAB:3D切换桌面 al ...
- C#读取和写入文件
一.读取文件 如果你要读取的文件内容不是很多, 可以使用 File.ReadAllText(FilePath) 或指定编码方式 File.ReadAllText(FilePath, Encoding) ...
- Python之列表&元组&字典
今天学习了Python的基本数据类型,做以下笔记,以备查用. 一.列表 列表的常用方法: 1.append()方法 def append(self, p_object): # real signatu ...
- 推荐学习c语言的几个开源项目
1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连 ...
- LeetCode OJ 54. Spiral Matrix
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...
- $each $position $sort $slice
$push 向数组中添加元素 $each 循环数据(循环添加数据到数组) $sort 对数组进行排序(1:升序:-1:降序.) $slice 对整个collection表进行数据裁减,用的时候一定要当 ...