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. ubuntu通过tnvm安装Nodejs

    第一步,先安装tvm tnvm(Taobao Node Version Manager)淘宝Node版本管理器 安装: 直接输入 wget -O- https://raw.githubusercont ...

  2. Windows10 Apache2.4 PHP7 MySQL 5.7安装教程

    最近细细的折腾了win10下PHP环境的安装过程,每次安装总是有小问题,现在总结一下.安装之前需要注意,下载的安装包(除MySQL)外必须统一是64位或者统一时32位. 一. MySQL5.7的安装 ...

  3. Android常用Permission

    位置相关: android.permission.WRITE_GSERVICES 允许程序修改Google服务地图(Allows an application to modify the Google ...

  4. IIS7部署MVC站点后,打开无法正常跳转到首页

    产品拿到安装包后想在本地安装测试一下,但是管理工具里没有IIS. 后来在windows功能里添加iis服务. 添加后成功安装. 但是第一次打开时,页面提示要“启用目录浏览”. 启用后,打开的却是站点目 ...

  5. [ An Ac a Day ^_^ ] CodeForces 677B Vanya and Food Processor 模拟

    题意: 你有一个榨汁机 还有n个土豆 榨汁机可以容纳h高的土豆 每秒可以榨k高的东西 问按顺序榨完土豆要多久 思路: 直接模拟 一开始以为是最短时间排了个序 后来发现多余了…… #include< ...

  6. Spring的Resource

    通过Spring Resource接口获取资源(取自http://haohaoxuexi.iteye.com/blog/2016305)目录1 Resource简介2 通过ResourceLoader ...

  7. FbinstTool(U盘启动盘制作工具) v1.606 免费绿色版

    软件名称: FbinstTool(U盘启动盘制作工具) v1.606 免费绿色版软件语言: 简体中文授权方式: 免费软件运行环境: Win7 / Vista / Win2003 / WinXP / W ...

  8. 【Machine Learning in Action --4】朴素贝叶斯分类

    1.概述 朴素贝叶斯分类是贝叶斯分类器的一种,贝叶斯分类算法是统计学的一种分类方法,利用概率统计知识进行分类,其分类原理就是利用贝叶斯公式根据某对象的先验 概率计算出其后验概率(即该对象属于某一类的概 ...

  9. 6.编写一个Java应用程序,该应用程序包括2个类:Print类和主类E。Print 类里有一个方法output()功能是输出100 ~ 999之间的所有水仙花数(各位数字的 立方和等于这个三位数本身,如: 371 = 33 + 73 + 13。)在主类E的main方法中来 测试类Print。

    Print类: package com.bao; public class Print { int g,s,b; void outPut() { for(int i=100;i<1000;i++ ...

  10. MS13-069(CVE-2013-3205) CCaret use-after-free Vulnerability Analysis (2014.9)

    MS13-069(CVE-2013-3205) CCaret use-after-free Vulnerability Analysis 1. Introduction In IE's standar ...