Java反射机制是在执行状态中,对于随意一个类,都可以知道这个类的全部属性和方法,对于随意一个对象,都可以调用它的随意一个方法和属性,这样的动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制,简单说:能动态获取类中的信息(类中全部),就是java的反射,也可以理解为对类的解剖

反射机制的基本应用场景:

   比方一个程序的应用程序(TomCat),为了提高其扩展性,会对外暴露一个接口。在外部定义一个类实现这个接口,可是在应用程序内部无法new对象,所以应用程序会提供一个配置文件,使用接口者能够将写好的而且实现接口的类名,写进配置文件。而应用程序利用反射机制会获取到指定名称的类的字节码文件并载入当中的内容进行调用,这就是反射机制的基本应用。

总结:反射技术提高了程序的扩展性。且应用简单,用户和程序之间的桥梁变为了配置文件

想要对一个类文件进行解剖。仅仅要获取该类的字节码文件就可以。

   现实中的事物,不断向上抽取其共性内容。能够得到类来描写叙述事物,反射机制中,也是将字节码向上抽取,用Class来描写叙述字节码文件,那么就能够产生对象,就能够提供方法,获取字节码文件的成员,如:名称、字段、构造函数、一般函数等全部内容,反射就是依靠该类来完毕的



反射呢,就是拿到.class文件,得到构造器。....构造对象,反着用。而不是得到.java文件

要想解剖一个类。必需要得到其字节码文件,就必须用到Class对象

定义演示类

public class Man {
private int age;
private String name;
public Man() {
super();
System.out.println("Man run");
}
public Man(int age, String name) {
super();
this.age = age;
this.name = name;
System.out.println("Man run yes"+this.name+this.age);
}
public void show(){
System.out.println(age+"..show.."+name);
}
private void privatemethod(){
System.out.println(age+"..method.."+name);
}
public void print(int num,String line){
System.out.println(num+"..print.."+line);
}
public static void staticmethod(){
System.out.println("..staticmethod..");
}
}

获取Class对象方式

要想对字节码文件进行解剖,必须获取字节码文件对象

获取字节码文件对象的方式有三种:

1.Object类中的getClass方法

用这样的方式。必须明白详细的类,并创建对象

public static void get_Class_Object() {

		Man man1 = new Man();
Class<?> clas1 = man1.getClass();
Man man2 = new Man();
Class<? > clas2 = man2.getClass(); System.out.println(clas1==clas2);
}

2.不论什么数据类型都具备一个静态属性.class来获取其相应Class对象

相对简单,可是还是须要明白类中的静态成员,扩展性不高

public static void get_Class_static() {

		Class<?

> cls1 = Man.class;
Class<? > cls2 = Man.class;
System.out.println(cls1==cls2);
}

3.仅仅要通过给定的类的字符串名称就能够获取该类(重点掌握)

能够用Class类中的方法来完毕

该方法就是forName();这中方式仅仅要有名称就可以

API:forName(String className)

返回与带有给定字符串名的类或接口相关联的 Class 对象。

API:forName(String name, boolean initialize,ClassLoader
loader)


使用给定的类载入器,返回与带有给定字符串名的类或接口相关联的 Class 对象。

	public static void get_Class() throws ClassNotFoundException {
//G:\java\fan\bin\fan\Man.class
//而默认的classpath路径是src、bin
String classname = "fan.Man";//明白是哪个包中的类
Class<?> cls = Class.forName(classname);
System.out.println(cls);
}

注意抛异常

获取Class中的构造函数

Man man = new Man();曾经new对象,先依据被new的类的名称。寻找该类的字节码文件,并载入进内存。并创建该字节码文件对象。并接着创建该字节码文件相应的Man对象

API:newInstance()

创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空參数列表的new 表达式实例化该类。假设该类尚未初始化,则初始化这个类。

实际上就是Man中的空參的构造函数

Man类中有空參构造函数

public static void reflect_Demo() throws ClassNotFoundException, InstantiationException, IllegalAccessException {

		String classname = "fan.Man";
//找寻该名称类文件。并载入进内存,产生Class对象
Class<? > cls = Class.forName(classname); Object obj = cls.newInstance();
}



Man类中无空參构造函数

Man man = new Man(11,"a");

假设直接调用上述方法,会抛出初始化异常InstantiationException

假设有空參构造函数,可是,是私有的private Man(){}。会抛出无效訪问异常IllegalAccessException

所以:当获取指定名称类中所体现的对象时,而对象初始化不使用空參数构造时。应该先获取其构造函数,通过字节码文件对象就可以完毕。getConstructor

API:getConstructor(Class<?

>... parameterTypes)

返回一个 Constructor 对象。它反映此 Class 对象所表示的类的指定公共构造方法。

API:getDeclaredConstructors()

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的全部构造方法。

Constructor对象中有方法new对象

API:newInstance(Object... initargs)

使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例。并用指定的初始化參数初始化该实例。

public static void reflect_Demo() throws Exception {

		String classname = "fan.Man";
Class<?> cls = Class.forName(classname); //參数数组,一个int基本数据类型相应的字节码是int.class
Constructor<?> constructor = cls.getConstructor(int.class,String.class);
//获取到了指定构造函数的对象 Object obj = constructor.newInstance(11,"a");
}

仅仅只是在配置文件的时候须要写明类名和构造函数的參数信息

PS:一般被反射的类一般都是带有空參,由于获取实例方便

获取Class中的字段

API:getField(String name)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

API:getFields()

返回一个包括某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的全部可訪问公共字段。

API:getDeclaredField(String name)

返回一个 Field 对象。该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

API:getDeclaredFields()

返回 Field 对象的一个数组。这些对象反映此 Class 对象所表示的类或接口所声明的全部字段。

	public static void reflect_Demo() throws Exception {

		String classname = "fan.Man";
Class<?> cls = Class.forName(classname);
Object object = cls.newInstance(); //Field field = cls.getField("name");//有age、name字段。仅仅能获取公有
Field field = cls.getDeclaredField("name");//仅仅能获取本类,包含私有
System.out.println(field); //获取字段的值......... //Object obj = field.get(object);
//System.out.println(obj);//反问失败由于其是私有的 //对私有字段的訪问取消权限检查。-> 暴力訪问
field.setAccessible(true);//Field的父类方法,改动其訪问权限
field.set(object, "a");//设置值
Object obj = field.get(object);
System.out.println(obj);//
}

API:AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言訪问控制检查的能力。

PS:不建议用暴力訪问的方式訪问数据

获取指定Class中的方法

获取一个无參方法

public static void reflect_Demo() throws Exception {

		String classname = "fan.Man";
Class<? > cls = Class.forName(classname); // Method[] methods = cls.getMethods();//获取本类及其父类全部公共方法
// methods = cls.getDeclaredMethods();//仅仅获取本类中。全部方法。包含私有 // for(Method M : methods){
// System.out.println(M);
// }
//拿一个无參方法
Method method = cls.getMethod("show", null);//注意与拿构造函数不同,方法名,方法參数列表
//Object obj = cls.newInstance();//无參构造
//method.invoke(obj, null);
Constructor<?> constructor = cls.getConstructor(int.class,String.class);
Object obj = constructor.newInstance(1,"a");//有參构造 method.invoke(obj, null);//对带有指定參数的指定对象调用由此 Method 对象表示的底层方法。
}

获取有參方法

	public static void reflect_Demo() throws Exception {

		String classname = "fan.Man";
Class<?> cls = Class.forName(classname); Method method = cls.getMethod("print", int.class,String.class);//方法參数列表
Object obj = cls.newInstance(); method.invoke(obj, 11,"a");//对获取到的方法进行调用
}

反射练习:

public class Computer {
public void run(){
System.out.println("Computer is run....");
}
public void UseInter(Inter p){//对外暴露接口。提高扩展性
if(p!=null){
p.open();
p.close();
}
}
}
public interface Inter {
public void open();
public void close();
}
public class NetCard implements Inter{
public void open() {
System.out.println("NetCard open....");
}
public void close() {
System.out.println("NetCard close...");
}
}
public class SoundCard implements Inter { public void open() {
System.out.println("SoundCard open...");
}
public void close() {
System.out.println("SoundCard close...");
}
}
public class Main {
public static void main(String[] args) throws Exception{ Computer com = new Computer();
com.run();
//com.UseInter(new SoundCard());//多态,可是这样写须要改动已有代码 //利用放射机制来完毕,获取Class文件,在内部实现创建对象
File conFile = new File("G:\\java\\fan\\bin\\fan\\inter.properties"); Properties pro = new Properties();
FileInputStream fis = new FileInputStream(conFile);
pro.load(fis);//将流中信息载入进集合
for(int x = 0; x < pro.size();x++){
String intername = pro.getProperty("Inter"+(x+1));
Class<?> cls = Class.forName(intername);//用Class去载入这个Inter子类
Object obj = cls.newInstance();//创建Inter对象
Inter p = (Inter)obj;
com.UseInter(p);
}
fis.close();
}
}



由于还没有学习XML,所以用properties取代

这两位大牛关于反射机制写的很好 点击打开链接   打开链接

能够说是涵盖了反射的全部基础内容

JAVA学习第六十四课 — 反射机制的更多相关文章

  1. JAVA学习第三十四课 (经常使用对象API)—List集合及其子类特点

    整个集合框架中最经常使用的就是List(列表)和Set(集) 一.List集合 && Set的特点 Collection的子接口: 1.List:有序(存入和取出的顺序一致),元素都有 ...

  2. JAVA学习第五十四课 — IO流(八)打印流 &amp; 序列流

    一.综合练习-文件清单列表 获取指定文件夹下,指定扩展名的文件(含子文件夹),并将这些文件的绝对路径写到一个文本文件里.也就是建立一个指定扩展名的文件列表 1.深度遍历 2.过滤器->容器 3. ...

  3. JAVA学习第六十二课 — TCP协议练习

    通过练习掌握TCP在进行传输过程中的问题 练习1:创建一个英文大写转换server client输入字母数据,发送给服务端,服务端收到后显示到控制台,并将该数据转成大写返回client,知道clien ...

  4. JAVA学习第六十五课 — 正則表達式

    正則表達式:主要应用于操作字符串.通过一些特定的符号来体现 举例: QQ号的校验 6~9位.0不得开头.必须是数字 String类中有matches方法 matches(String regex) 告 ...

  5. JAVA学习第五十二课 — IO流(六)File对象

    File类 用来给文件或者目录封装成对象 方便对文件与目录的属性信息进行操作 File对象能够作为參数传递给流的构造函数 一.构造函数和分隔符 public static void FileDemo( ...

  6. JAVA学习第五十九课 — 网络编程概述

    网络模型 OSI(Open System Interconnection)开放系统互连:參考模型 TCP/IP 网络通讯要素 IP地址 port号 传输协议 网络參考模型 七层OSI模型的基本概念要了 ...

  7. 【Java学习笔记之三十四】超详解Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  8. JAVA学习第三十二课(经常使用对象API)- 基本数据类型对象包装类

    将基本数据类型(8种:int..)封装成对象的优点就是能够在对象中封装很多其它的功能和方法来操控该数据 常见的操作就是:用于基本数据类型与字符串之间的转换 基本数据类型对象包装类一般用于基本类型和字符 ...

  9. Java学习笔记(十四)——Java静态工厂

    [前面的话] 每天过的还行,对我来说,只要让自己充实,生活就会是好的. 学习Java工场方法的原因是最近在使用Spring框架做一个系统,其中有一个注入的方法是使用静态工场方法注入,所以学习一下,基础 ...

随机推荐

  1. 【转】DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的两种方式(dllexport与.def文件) DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport):另外一种方式是:采用模块定义 ...

  2. 第一个WebDriver脚本

    1.cmd下安装selenium,输入pip install selenium 2.下载Firefox浏览器的驱动程序,https://github.com/mozilla/geckodriver/r ...

  3. js 函数节流和防抖

    js 函数节流和防抖 throttle 节流 事件触发到结束后只执行一次. 应用场景 触发mousemove事件的时候, 如鼠标移动. 触发keyup事件的情况, 如搜索. 触发scroll事件的时候 ...

  4. 第五讲:Fast RTL-level verification

    1.good code styles 2.+rad compile time switch  for compile 1.了解VCS 的架构  <===这方便了解不多 parser / even ...

  5. 如何将已经安装从chrome扩展程序导出备份为.CRX文件?

    之前介绍过CRX Extractor可以从chrome应用商店下载备份扩展程序,有读者朋友问说:如果 Google Chrome扩展程序已经从 Chrome应用商店下架,还有没有方法下载呢?通常网路上 ...

  6. 【练习】reserving.kr 之imageprc write up

    补充:c++ builder 与 windows  API经典范例 #include <vcl.h> #pragma hdrstop #include "Unit1.h" ...

  7. POJ 1979 Red and Black (DFS)

    Description There is a rectangular room, covered with square tiles. Each tile is colored either red ...

  8. cxLookupCombobox的多字段模糊匹配

    查了网上很多资料,懒人输入:通过程序使用过滤对话达到自己的目的: 用到cxFilter单元: cbb_DoctorOrder.Properties.View.DataController.Filter ...

  9. Haproxy配置文件详解

    #/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -st `cat /var/run/haproxy.pid` ################ ...

  10. BeautifulSoup4系列一

    前言 以博客园为例,爬取我的博客上首页的发布时间.标题.摘要,本篇先小试牛刀,先了解下它的强大之处,后面讲beautifulsoup4的详细功能. 一.安装 1.打开cmd用pip在线安装beauti ...