java中的反射机制,以及如何通过反射获取一个类的构造方法 ,成员变量,方法,详细。。
首先先说一下类的加载,流程。只有明确了类这个对象的存在才可以更好的理解反射的原因,以及反射的机制。
一、 类的加载
- 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
- 加载
- 就是指将class文件读入内存,并为之创建一个Class对象---> 而这个对象就是我们反射中将要使用的对象。
- 任何类被使用时系统都会建立一个Class对象。
- 连接
- 验证 是否有正确的内部结构,并和其他类协调一致;
- 准备 负责为类的静态成员分配内存,并设置默认初始化值;
- 解析 将类的二进制数据中的符号引用替换为直接引用。
- 初始化 就是常规的一个类的的初始化步骤,有静态先静态。。。。忘记的自己回去看~
二、类初始化时机
· 创建类的实例
· 访问类的静态变量,或者为静态变量赋值
· 调用类的静态方法
· 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
· 初始化某个类的子类
· 直接使用java.exe命令来运行某个主类
三.类加载器
l 类加载器
- 负责将.class文件加载到内在中,并为之生成对应的Class对象。
- 虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
l 类加载器的组成
- Bootstrap ClassLoader 根类加载器
- Extension ClassLoader 扩展类加载器
- Sysetm ClassLoader 系统类加载器
四、类加载器的作用
1. Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
2.Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
3. Sysetm ClassLoader 系统类加载器 (我们自己定义的类一般在这里)
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
//------------------------------------------------代码的分割线
//下面首先介绍的是第一步如何通过Class的方法来获取指定类的class对象,没有该对象就无从反射谈起
/*
2 * 反射:就是通过class文件对象,去使用该文件的成员变量,构造方法,成员方法。
3 * 在以前的时候一般都是通过创建对象然后通过对象取调用该类的方法
*
* Class类:通过Class来得到被加载类的三个属性同时每一个属性又通过对应的类进行创建对象来调用方法来使用被加载类的方法
* 成员变量: Field
* 构造方法: Constructor
* 成员方法: Method
*
* 获取class文件对象的方式:
* A:object类的getClass()方法
* B:数据类的静态属性class(只要是数据类型都有这个方法)
* C:class类中的静态方法
* public static Class<?> forName(String className)
* String className:此处需要的是类的带包名的全路径否则报错,java.lang.ClassNotFoundException: Person
*
*
* 实际开发的时候一般使用的是第三种。因为该方法使用的是配置文件,可以在配置文件中直接进行配置,可以让该字符串变化。
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1
Person p = new Person();
Class c = p.getClass(); Person p2 = new Person();
Class c2 = p.getClass(); System.out.println(p == p2);
System.out.println(c == c2); // 方式2
Class c3 = Person.class; // 方式3
//反射机制.Person 这里很容易出错,我自己写的时候就经常不小心写错。写错了还不好检查。
/*
* 由于写一个类的全路径经常会出错,所以尽量不自己手写,
* 1.点开那个类里面有一个copy qualifield Name的选项,
* 2.直接在外面写通过辅助自动补齐手段进行检测,在需要的那个类里面找到package。
*/
Class c4 = Class.forName("反射机制.Person");
System.out.println(c == c4); }
}
//---------------------------------------------------------
//下面给出上面再main方法中使用的person类,相当简单的一个类
//在后面会陆续使用该类,进行构造方法,字段,以及成员方法的调用,后面就不再给出该类,该类一直代表person
public class Person {
private String name;
int age;
public String address;
public Person() {
}
private Person(String name) {
this.name = name;
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public void show() {
System.out.println("show");
}
public void method(String s) {
System.out.println("method " + s);
}
public String getString(String s, int i) {
return s + "---" + i;
}
private void function() {
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
//---------------------------------------------
//通过反射获取一个类的构造方法并进行使用。包括如何访问Person类的公共无参构造方法,公共有参构造方法,以及私有带参构造
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; /*
* 通过反射机制获取构造方法
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象,此处仍然是上面的person类.
Class c = Class.forName("反射机制.Person"); // 获取构造方法
// public Constructor [] getConstructors() => 公共构造方法所有的
// public Constructor [] getDeclaredConstructors() => 所有的构造方法 ,一旦添加Declared单词修饰获取一般是全部的声明包括自有private,protected。 // Constructor[] cons = c.getConstructors();
Constructor[] cons = c.getDeclaredConstructors(); //这种方法虽然获取到了所有的构造方法,但是没什么作用,因此需要使用下面的方法获取单个的构造方法
for (Constructor con : cons) {
System.out.println(con);
} // 获取单个构造方法,
// public Constructor getConstructor(Class<?>... parameterTypes)
// 该方法的参数表示的是:你要获取的构造方法的构造参数的个数以及class字节码文件对象 Constructor con = c.getConstructor(); // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
// public T newInstance(Object... initargs) Object obj = con.newInstance(); // 此处创建的是Person类的对象实例, // 此处创建的是Person类的对象实例,由于是无参构造因此不需要参数。
System.out.println(obj); // Person [name=null, age=0, address=null]
/*
* 下面的代码是:通过反射区获取带参数的构造方法
*/
// 获取指定参数的构造函数
// public Constructor getConstructor(Class<?>... parameterTypes)
/*
* 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 parameterTypes 参数是 Class 对象的一个数组,
*/
Constructor con2 =c.getConstructor(String.class, int.class,
String.class); // 通过构造方法创建对象
// ublic T newInstance(Object... initargs)
Object obj2 = con.newInstance("java", 22, "武汉");
System.out.println(obj2);
//----------------------------------
//通过反射获取私有构造方法并使用。
// 获取私有构造器 ---> getDeclaredConstructor
// 如果直接使用getConstructor则会导致没有该方法的异常NoSuchMethodException
Constructor con3 = c.getDeclaredConstructor(String.class); // 私有方法直接访问:--->报错IllegalAccessException非法访问异常
/*
* 暴力访问 public void setAccessible(boolean flag) 将此对象的 accessible
* 标志设置为指示的布尔值。 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。 值为 false
* 则指示反射的对象应该实施 Java 语言访问检查。
*/ con3.setAccessible(true); // 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
Object obj3 = con.newInstance("android");
System.out.println(obj3); }
}
//-------------------------------------------------
//下面的代码是如何通过反射获取一个类的公有成员变量私有成员变量,并进行赋值显示
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; /*
* 通过反射获取成员变量并使用
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件class对象
Class c = Class.forName("反射机制.Person"); // 获取所有的成员变量,
// Field[] fields = c.getFields(); 获取所有的公共成员变量,放在数组中不易操作。
// Field[] fields = c.getDeclaredFields(); 获取所有成员变量,放在数组中不易操作。 // 通过无参构造方法获取对象,有了对象才好对成员变量进行赋值,即使在反射中成员变量仍然是属于对象的。
Constructor con = c.getConstructor();
Object obj = con.newInstance();
//System.out.println(obj); // 获取单个的成员变量,指定成员变量的名字---address
Field addressField = c.getField("address"); // 对于成员变量,一般是通过对象 : obj.address = "777"进行赋值,
// public void set(Object obj, Object value)
// 上面方法的意思是将指定对象变量obj上此 Field 对象addressField表示的字段设置为指定的新值value 。 addressField.set(obj, "java"); // 给obj对象的addressField字段设置值为value:java,这个地方很拗口,与java基本思路背道而驰。
System.out.println(obj); // 获取name并对其赋值,name是私有成员变量。
Field nameField = c.getDeclaredField("name");
//IllegalAccessException,暴力访问
nameField.setAccessible(true);
nameField.set(obj, "android");
System.out.println(obj); // 获取age并对其赋值,age是私有成员变量。
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj, 25);
System.out.println(obj); }
}
//-------------------------------------------
// 获取类中的所有方法,公共方法,私有方法。并进行使用。
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; /*
* 获取类中的所有方法
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception { // 获取字节码class对象
Class c = Class.forName("反射机制.Person"); // 获取所有方法
// Method[] methods = c.getMethods(); //该方法获取获取本身的以及父亲的所有公共方法,此处无意义。
Method[] methods5 = c.getDeclaredMethods(); // 获取自己的所有方法,加入了Declared,在实际使用中可以不管你需要的东西的公共还是私有直接使用Declared修饰的方法
// for (Method method : methods) {
// System.out.println(method);
// } // 获取对象,由于其它构造麻烦一些,在获取对象时一律使用无参构造。
Constructor con = c.getConstructor();
Object obj = con.newInstance(); // 获取单个的指定方法
// public Method getMethod(String name, Class<?>... parameterTypes)
// 第一个参数表示的是方法名,第二个参数表示的方法的参数class类型。
// show方法是公共,无形参的方法public void show() { }
Method method1 = c.getDeclaredMethod("show");
// public Object invoke(Object obj, Object... args)
30 // 返回值是object接受,第一个参数表示对象是谁,第二个参数表示调用该方法的实际参数(形参)。
31 // 没有返回值就不写,
method1.invoke(obj); // 调用obj对象的mehod1方法, // 带一个参数方法无返回值的方法调用, public void method(String s){}
Method method2 = c.getMethod("method", String.class);
method2.invoke(obj, "java"); // 带两个形参,有返回值的方法的调用public void method(String s),
Method method3 = c.getMethod("getString", String.class,
int.class);
Object objStr = method3.invoke(obj, "java", 50);
System.out.println("Method3" + objStr); //私有方法
Method method4 = c.getDeclaredMethod("function");
method4.setAccessible(true); //暴力访问
method4.invoke(obj); }
}
java中的反射机制,以及如何通过反射获取一个类的构造方法 ,成员变量,方法,详细。。的更多相关文章
- Java反射机制demo(四)—获取一个类的父类和实现的接口
Java反射机制demo(四)—获取一个类的父类和实现的接口 1,Java反射机制得到一个类的父类 使用Class类中的getSuperClass()方法能够得到一个类的父类 如果此 Class 表示 ...
- OC学习--OC中的类--类的定义,成员变量,方法
1. 类的定义 >用关键字@interface进行声名 @end 结束 >所有的类有一个基类NSobject >类名 也是标示符 第一个字母大写 如果多个字母组成 每个单词的首字母 ...
- java反射机制,以及对反射机制的了解,如有差池欢迎点评(初学者勿喷)
本人学习java时间不长,但是对java很感兴趣,知道有博客园这个平台果断的注册,记录我的java成长日记,这也是我的处女作,虽然很菜但是还是希望大家能见证我的成长,觉得可以的可以和我讨论一起学习 在 ...
- java反射机制,以及对反射机制的了解
反射是什么?反射有什么用?我相信大家在开始学的时候都会有疑惑,直到如今我学的还不够深入只能简单的说说反射的作用,理论的我也听得很迷糊,接下来我就以几个例子来 写写反射的用处: 494696003群,有 ...
- Java反射机制demo(三)—获取类中的构造函数
Java反射机制demo(三)—获取类中的构造函数 1,获取类中所有的构造函数 如下面的代码中所示,这个类中显式的构造函数有五个. 空构造: public UserInfo() 带参构造有四个: pu ...
- Java反射机制详解(1) -反射定义
首先,我们在开始前提出一个问题: 1.在运行时,对于一个java类,能否知道属性和方法:能否去调用它的任意方法? 答案是肯定的. 本节所有目录如下: 什么是JAVA的反射机制 JDK中提供的Refle ...
- java中wait/notify机制
通常,多线程之间需要协调工作.例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕.如果图片还没有下载完,d ...
- 【Java】深入理解Java中的spi机制
深入理解Java中的spi机制 SPI全名为Service Provider Interface是JDK内置的一种服务提供发现机制,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用 ...
- 【夯实基础】- Java中的fail-fast机制
转载自:Java中的fail-fast机制 遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过普通的for删除删除符合条件 ...
随机推荐
- linux查看防火墙状态及开启关闭命令(转)
存在以下两种方式: 一.service方式 查看防火墙状态: [root@centos6 ~]# service iptables status iptables:未运行防火墙. 开启防火墙: [ro ...
- 第一个thinkphp入口文件
ThinkPHP3.1.3_full已下载 网站根目录下编辑一个入口文件index.php <?php define('APP_NAME','Index'); //项目名称 define('AP ...
- RabbitMQ学习总结 第二篇:快速入门HelloWorld
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- [BS-08]注意Xcode自动提示好用但极易出错,务必看清方法的名称
今日在写一个UIBarButtonItem的分类时,在Xcode自动提示时,因未仔细查看,错将需要用到setBackgroundImage的地方,选择成setImage,结果导致button的boun ...
- Java文件操作①——XML文件的读取
一.邂逅XML 文件种类是丰富多彩的,XML作为众多文件类型的一种,经常被用于数据存储和传输.所以XML在现今应用程序中是非常流行的.本文主要讲Java解析和生成XML.用于不同平台.不同设备间的数据 ...
- pptp记录用户登陆日志
pptp vpn记录用户登录和流量信息(转) 这个问题困扰了我很久,终于在pppd的man文档里,发现了踪迹.在man中的SCRIPTS下有一系列的参数,其中PEERNAME就是登陆的用户名,并且在/ ...
- 为Virtual Studio Code配置Python调试插件(Ubuntu14.04)
详情见以下python for virtual studio code插件的链接: python 安装依赖 1.Python is installed on the current system Pa ...
- C++Primer 第十二章
//1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间. // shared_ptr:允许多个指针指向同一个对象. // unique_ptr:独占所指 ...
- HTML--表单,图片热点,网页划区和拼接
一.图片热点 规划出图片上的一个区域,可以做出超链接,直接点击图片区域就可以完成跳转的效果. 示例: <img src="/ usemap="longzhu"> ...
- Java基础(31):String的大小写转换、分离成数组、==与equals()的区别(String类)
继续来看 String 类常用的方法,如下代码所示: 运行结果: 那么,“==” 和 equals() 有什么区别呢? ==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象 eq ...