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. jQuery第十一章

    第十一章 一.jQuery性能优化 1.使用最新版本的jQuery类库. 2.使用合适的选择器 (1)$(“#id”) :使用id来定位DOM元素是最佳提高性能的方式. (2)$(“p”) :标签选择 ...

  2. laravel5.2/laravel5.3入门指南 Windows 上快速安装并运行 Laravel 5.x

    1 首先要搭建本地服务器环境推荐phpstudy2016及wampServer3.0.6 下载链接可参考 http://www.cnblogs.com/zzcit/p/5823742.html 注意一 ...

  3. Python学习笔记_Chapter 7web开发

    1.web应用元素 a.成员: web浏览器 web服务器 b.行为: web请求: 请求内容: 静态内容:如html文件,图像. 动态内容:需服务器运行一个程序进而做出响应. 网关接口&CG ...

  4. osg蝴蝶纹理

    #include <osgViewer/Viewer> #include <osgDB/WriteFile> #include <osg/StateSet> #in ...

  5. 站在Java的角度看LinkedList

    站在Java的角度看,玩队列不就是玩对象引用对象嘛! public class LinkedList<E> implements List<E>, Deque<E> ...

  6. Codeforces Round #256 (Div. 2) B Suffix Structures

    Description Bizon the Champion isn't just a bison. He also is a favorite of the "Bizons" t ...

  7. JPA 系列教程17-继承-独立表-TABLE_PER_CLASS

    PerTable策略 每个具体的类一个表的策略 举例 这种映射策略每个类都会映射成一个单独的表,类的所有属性,包括继承的属性都会映射成表的列. 这种映射策略的缺点是:对多态关系的支持有限,当查询涉及到 ...

  8. PHP通过url下载远程图片到本地

    function GrabImage($url,$filename) { if($url==""):return false;endif; ob_start(); readfile ...

  9. Android中的selector

    android背景选择器selector用法汇总 (2011-04-19 13:40:00) 转载▼ 标签: android selector 背景选择器 it 分类: java/vb/Android ...

  10. Heap Operations(模拟题)

     Heap Operations time limit per test 1 second memory limit per test 256 megabytes input standard inp ...