前几天上REST课,因为涉及到Java的反射机制,之前看过一直没有用过,有些遗忘了,周末找了些资料来重新学习,现在总结一下,加深印象。

什么是反射机制?

参考百度百科对java反射机制的定义:

“JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。”

我们通过一些例子,更好理解反射机制。

Class类

我们知道Java是一门面向对象语言,在Java的世界里,万物皆为对象,比如我们有一个Person类:

public class Person {

}

我们创建一个Person类的实例,Person person = new Person();  那么这个person,就是Person类的实例对象。

那么既然万物都为对象,所以类也是对象。

类是什么的对象呢?类是Class类的对象,表示方式有三种:

//第一种,任何一个类都有一个隐含的静态成员变量class
Class c1 = Person.class; //第二种,已经知道该类的对象,通过getClass()获得
Class c2 = person.getClass(); //第三种,Class类的forName()方法
Class c3 = Class.forName("Person"); //这里,c1,c2,c3都是Class类的实例,我们称c1, c2 ,c3为Person类的类类型
//不难看出,c1 == c2结果是true, c2 == c3结果也是true

通过类的类类型,我们经常会用到的方法就是newInstance()方法,通过该方法可以创建该类的实例:

Person personA = new Person(); //直接new一个实例
Person personB = Person.class.newInstance(); //通过newInstance()方法获得Person的实例 //在学习JAVAEE时候,newInstance()方法我们最常见于获取数据库驱动
Class.forName("com.mysql.jdbc.Driver").newInstance(); //需要注意的是,在使用newInstance()方法的前提是该类必须要有无参构造方法

动态加载类:

编译时刻加载类称为静态加载,运行时刻加载类称为动态加载,使用new方法新建实例即为静态加载类,在编译时候就要加载全部类。这里我们举一个例子:

为了更好的区分编译和运行,我们不适用IDE工具,而使用记事本来实现这个例子:

//我们举女娲造人的例子,创建一个CreatePerson类
public class CreatePerson {
public static void main(String[] args) {
if(args[0].equalsIgnoreCase("man")) { //如果从命令行传入的参数为man 则创建Man的实例并调用say()方法
new Man().say();
}
if(args[0].equalsIgnoreCase("woman")) { //如果从命令行传入的参数为woman 则创建Woman的实例并调用say()方法
new Woman().say();
}
}
} //CreatePerson类用到了2个类,分别是Man和Woman。
//但是我们现在只创建Man类
public class Man {
public void say() {
System.out.println("I am a man !");
}
}

我们在CMD中编译CreatePerson,看看会发生什么:

提示我们找不到Woman这个类。这就是静态加载,在编译时刻需要加载全部类。那么问题来了,如果我要写一个程序,里面有100个功能,这100个功能分别由100个类实现,那么一旦缺少一个类,这整个程序是不是就不能用了。

为了解决这个问题,我们可以使用动态加载。我们把上面这个例子改一下:

//创建一个Person接口
public interface Person {
void say();
} //修改Man类,继承Person接口
public class Man implements Person{
public void say() {
System.out.println("I am a man !");
}
} //修改CreatePerson类,实现动态加载类
public class CreatePerson{
public static void main(String[] args) { try{
//动态加载类
Class c = Class.forName(args[0]);
//通过类的类类型,创建该类实例对象
Person person = (Person)c.newInstance();
person.say(); } catch(Exception e) {
e.printStackTrace();
}
}
}

这个时候,我们再进行编译:

没有报错了,那么我们继续把Man编译,再运行一下:

如果我们在命令行中输入的参数是Woman呢?

抛出ClassNotFoundException异常。因为我们并没有创建Woman类,所以如果以后需要创建Woman类实例,我们只需要新建一个Woman类,并实现Person接口就行了。

通过反射机制,获得类的信息

在Java反射机制的定义中有:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。下面是一个实例:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class ClassUtil {
/**
* 获取成员函数的信息
*/
public static void getClassMethodMessage(Object obj) {
Class c = obj.getClass();
//获取类的名称
//System.out.println(c.getName()); /**
*
* Method类,方法对象
*getMethods方法获得所有public的方法,包括继承而来
*getDeclaredMethods是获取该类自己的声明的方法
*/
Method[] ms = c.getMethods();
for(int i = 0; i < ms.length; i++) {
//得到方法的返回值类型的类类型
Class returnType = ms[i].getReturnType();
System.out.print(returnType.getName() + " ");
//得到方法的名称
System.out.print(ms[i].getName() + "(");
//获取参数类型
Class[] paramTypes = ms[i].getParameterTypes();
for(Class class1:paramTypes) {
System.out.print(class1.getName() + ",");
}
System.out.println(")");
} } public static void getFieldMessage(Object obj) {
Class c = obj.getClass(); /**
* 成员变量也是对象
* java.lang.reflect.Field
*
*/
Field[] fs = c.getDeclaredFields();
for(Field field:fs) {
//得到成员变量类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成员变量的名称
String fieldName = field.getName();
System.out.println(typeName + " " + fieldName); }
} public static void printConMessage(Object obj) {
Class c = obj.getClass();
/**
* 构造函数也是对象
*
*/
Constructor[] cs = c.getConstructors();
for (Constructor constructor : cs) {
System.out.print(constructor.getName() + "(");
//获取构造函数参数列表------>参数列表的参数类型
Class[] paramType = constructor.getParameterTypes();
for (Class class1 : paramType) {
System.out.print(class1.getName() + ",");
}
System.out.println(")");
} } public static void main(String[] args) {
String s = "hello";
getFieldMessage(s);
ClassUtil.printConMessage(s);
getClassMethodMessage(s);
}
}

方法的反射操作

可以通过方法的反射操作实现方法的调用:

import java.lang.reflect.Method;

public class MethodDemo1 {
public static void main(String[] args) {
//要获取print(int, int)
//要获取类的方法就要获取类的信息,获取类的信息就要获取类的类类型
A a1 = new A();
Class c = a1.getClass();
//2,获取方法 名称和参数列表
//getMethod获取的是public的方法
try {
Method m = c.getDeclaredMethod("print", int.class,int.class); //方法的反射操作
//a1.print(10, 20);方法的反射操作,用m来进行方法调用和前者效果一致
Object obj = m.invoke(a1, 10,20);//如果方法有返回值返回值,没有就null } catch (Exception e) { e.printStackTrace();
}
} } class A {
public void print(int a , int b) {
System.out.println(a + b);
} public void print(String a , String b) {
System.out.println(a.toUpperCase() + "," + b.toUpperCase());
}
}

以上就是我对Java反射机制的学习和理解,如果有错误,望指出,以便及时更正!谢谢!

Java反射机制——学习总结的更多相关文章

  1. JAVA反射机制—学习总结

    最近收到很多关于Java反射机制的问题留言,其实Java反射机制技术方面没有太多难点,或许是大家在学习过程中遗漏了细小知识点,导致一些问题无法彻底理解,现在我们简单的总结一下,加深印象.什么是反射机制 ...

  2. Java反射机制学习与研究

    Java反射机制:可以获取正在运行时的Java对象. 1.判断运行时对象对象所属的类. 2.判断运行时对象所具有的成员变量和方法. 3.还可以调用到private方法,改变private变量的值. S ...

  3. Java反射机制学习

    Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”. 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答 ...

  4. JAVA反射机制学习随笔

    JAVA反射机制是用于在运行时动态的获取类的信息或者方法,属性,也可以用来动态的生成类,由于所有类都是CLASS的子类,我们可以用一个CLASS类的实例来实例化各种类 例如: Class<?&g ...

  5. java反射机制学习小结

    之前一直对java的反射机制理解得很模糊,今天因为学习spring,所以花了些时间总算把它理顺了,记录一下 另外,推荐读读这篇文章,写的挺好的http://blog.csdn.net/woshixuy ...

  6. java反射机制学习笔记

    内容引用自:https://www.cnblogs.com/wkrbky/p/6201098.html https://www.cnblogs.com/xumBlog/p/8882489.html,本 ...

  7. Java 反射机制学习资料

    Java反射——引言 Java反射——Class对象 Java反射——构造函数 Java反射——字段 Java反射——方法 Java反射——Getter和Setter Java反射——私有字段和私有方 ...

  8. java反射机制学习代码

    根据 http://www.iteye.com/topic/137944 文档进行学习 代码如下: package reflectTest; import java.lang.reflect.*; i ...

  9. Java反射机制的学习

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

随机推荐

  1. 本地安装配置Gradle及IDEA使用本地Gradle

    一.下载Gradle   下载地址:http://services.gradle.org/distributions/   下载版本的bin.zip 二.配置环境变量 三.验证   在cmd模式下查看 ...

  2. 利用python第三方库提取PDF文件的表格内容

    小爬最近接到一个棘手任务:需要提取手机话费电子发票PDF文件中的数据.接到这个任务的第一时间,小爬决定搜集各个地区各个时间段的电子发票文件,看看其中的差异点.粗略统计下来,PDF文件的表格框架是统一的 ...

  3. Mongdb的基本操作及java中用法

    Mongdb中所有数据以Bson(类似JSON)的格式存在,可以存储集合,map,二进制文件等多种数据类型. 数据库的常用操作 use [数据库名称];//有就选中,没有就添加并选中show dbs; ...

  4. $tarjan$简要学习笔记

    $QwQ$因为$gql$的$tarjan$一直很差所以一直想着要写个学习笔记,,,咕了$inf$天之后终于还是写了嘻嘻. 首先说下几个重要数组的基本定义. $dfn$太简单了不说$QwQ$ 但是因为有 ...

  5. JVM性能监测工具——VisualVM

    Java本身自带了有好几个jvm监测工具,其中jconsole和jvisualvm这两个工具具有图形化界面,可以监测到cpu.类.线程.堆等一些参数,而且具有远程监控的能力. 启动:打开cmd命令窗口 ...

  6. jmeter 5.1版本更新说明

    版本5.1 摘要 新的和值得注意的 不兼容的变化 Bug修复 改进 非功能性变化 已知问题和解决方法 谢谢 新的和值得注意的 核心改进 JDBC测试已得到改进,能够设置init SQL语句并添加与不支 ...

  7. 用Eclipse和Tomcat搭建一个本地服务器

    服务器软件环境 Eclipse oxygen Tomcat 9.0 SQL Sever 2014 参考资料 https://blog.csdn.net/qq_21154101/article/deta ...

  8. 应届生/社招面试最爱问的几道Java基础问题

    本文已经收录自笔者开源的 JavaGuide: https://github.com/Snailclimb ([Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识)如果觉得不错 ...

  9. 如何对N个接口按比例压测

    随着微服务盛行,公司的服务端项目也越来越多.单一的接口性能测试并不能准确反映某个服务的总体处理能力,在服务功能划分比较清晰的架构下,对于某一服务的总体性能测试也相对变得简单.下面分享一个对于某个模块对 ...

  10. OOP之重载

    PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的. 属性的重载通过调用类中的__set,__get,__isset,__unset方法来分别实现对不存在属性的赋值.读取.判断属性是否设 ...