1.类的加载概述:当程序要使用某个类时,如果该类还没有被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化
(1)加载:就是指将class文件读入内存,并为之创建一个class对象。任何类被使用时系统都会建立一个class对象
(2)连接:分为验证(是否有正确的内部结构,并和其他类协调一致),准备(负责为类的静态成员分配内存,并设置默认初始化值), 解析(将类的二进制数据中的符号引用替换为直接引用)三步。
(3)初始化:字节码对象加载,默认初始化等等
2.加载时机
(1)创建类的实例
(2)访问类的静态变量,或者为静态变量赋值
(3)调用类的静态方法
(4)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
(5)初始化某个类的子类
(6)直接使用java.exe命令来运行某个主类
3.类加载器的概述:负责将.class文件加载到内存中,并为之生成对应Class对象。
Bootstrap ClassLoader 根类加载器:也被称为引导类加载器,负责Java核心类的加载
Extension ClassLoader 扩展类加载器:负责JRE的扩展目录中jar包的加载
System ClassLoader 系统类加载器:负责再JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的 jar包和类路径
4.反射:
(1)Java反射机制实在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
(2)对于任意一个对象,都能够调用它的任意一个方法和属性
(3)这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
(4)要想解剖一个类,必须先要获取到该类的字节码文件对象
(5)而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象
5.反射的三种方式:通过三种方式获取字节码对象
(1)Object类的getClass()方法,判断两个对象是否是同一个字节码文件
(2)静态属性class,锁对象
(3)Class类中静态方法forName(),读取配置文件
6.通过反射获取带参构造方法并使用
Class类的newInstance()方法是使用该类无参的构造函数创建对象,如果一个类没有无参的构造函数,就不能这样创建,但 是可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的 newInstance("aa",11)方法创建对象
7.通过反射获取成员变量并使用
Class.getField(String)方法可以获取类中的指定字段(可见的),如果是私有的可以用getDeclaredField("name")方法获取,通过 set(obj,"bb")方法可以设置指定对象上该字段的值,如果是私有的需要先调setAccessible(true)设置访问权限,用获取的指定 的字段调get(obj)可以获取指定对象中该字段的值
8.通过反射获取方法并使用
Class.getMethod(String,Class...)和Class.getDeclaredMethod(String,Class...)方法可以获取类中的指定方法,
调用invoke(Object,Object)可以调用该方法,Class.getMethod("eat") invoke(obj) Class.getMethod("eat",int.class)
invoke(obj,10)
9.通过反射越过泛型检查
ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据
10.通过反射写一个通用的设置某个对象的某个属性值为指定的值
public void setProperty(Object obj,String propertyName,Object value){},此方法可将obj对象中名为propertyName的属性的值 设置为value
package pra_25;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import pra_01.j_07;
public class J_47 {
/**
* @param args
* @throws ClassNotFoundException
* @throws IOException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws Exception {
Class c1=Class.forName("pra_01.j_07");
Class c2=j_07.class;
j_07 j07=new j_07();
Class c3=j07.getClass();
System.out.println(c1==c2); //true
System.out.println(c2==c3); //true
Qe q=new Qe();
q.eat(new A());
q.eat(new B());
//Class.forName()读取配置文件
BufferedReader br=new BufferedReader(new FileReader("config1.properties"));
Class c4=Class.forName(br.readLine());
All a1=(All) c4.newInstance(); //父类引用指向子类对象
Qe q3=new Qe();
q3.eat(a1);
//6.通过反射获取带参构造方法并使用
Class c5=Class.forName("pra_25.People");
Constructor cs=c5.getConstructor(String.class,int.class); //获取有参构造
People p=(People) cs.newInstance("aa",11); //通过有参构造创建对象
System.out.println(p);
//7.通过反射获取成员变量并使用
Class c6=Class.forName("pra_25.People");
Constructor cs2=c6.getConstructor(String.class,int.class); //获取有参构造
People p2=(People) cs2.newInstance("bb",22); //通过有参构造创建对象
/* //因为变量私有,所以不行
Field f=c6.getField("name"); //获取姓名字段
f.set(p2, "cc"); //修改姓名的值
*/
Field f=c6.getDeclaredField("name"); //暴力反射获取字段
f.setAccessible(true); //去除私有权限
f.set(p2, "cc");
System.out.println(p2);
//8.通过反射获取方法并使用
Class c7=Class.forName("pra_25.People");
Constructor cs3=c6.getConstructor(String.class,int.class);
People p3=(People) cs3.newInstance("bb",22);
Method me=c7.getMethod("eat"); //获取eat方法
me.invoke(p3); //运行eat方法
Method me2=c7.getMethod("eat", int.class); //获取有参的eat方法
me2.invoke(p3, 10);
//9.通过反射越过泛型检查,泛型只有在编译期才做语法检查,在运行期会被擦除掉
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(111);
Class c8=Class.forName("java.util.ArrayList"); //获取字节码对象
Method me3=c8.getMethod("add", Object.class); //获取add方法
me3.invoke(list, "abc");
System.out.println(list); //[111, abc]
//10.通过反射写一个通用的设置某个对象的某个属性值为指定的值
Person pe=new Person("qq",22);
System.out.println(pe); //Person [name=qq, age=22]
Tool t=new Tool();
t.setProperty(pe, "name", "www");
System.out.println(pe); //Person [name=www, age=22]
}
}
interface All{
public void eat();
}
class A implements All{
public void eat(){
System.out.println("a");
}
}
class B implements All{
public void eat(){
System.out.println("b");
}
}
class Qe{
public void eat(All one){
one.eat();
}
}
class Person{
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
以下是举例是用到的两个类
People.java
package pra_25;
public class People{
private String name;
private int age;
/*
public People() {
super();
}
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public People(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
People other = (People) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "People [name=" + name + ", age=" + age + "]";
}
public void eat(){
System.out.println("i like it!");
}
public void eat(int num){
System.out.println("i like it!+"+num);
}
}
Tool.java
package pra_25;
import java.lang.reflect.Field;
public class Tool {
//此方法可将obj对象中名为propertyName的属性的值设置为value
public void setProperty(Object obj,String propertyName,Object value) throws Exception{
Class c=obj.getClass(); //获取字节码对象
Field f=c.getDeclaredField(propertyName); //暴力反射获取字段
f.setAccessible(true); //去除权限
f.set(obj, value);
}
}