文章目录
1.类加载
类(文件 Hello.class)–>JVM 加载到内存的过程。
1.1类加载的顺序
1.1.1 加载: 加载class文件
内存中创建一个特殊对象Class
Car c = new Car();
System.out.println(c.getClass());
System.out.println(Car.class);
Class<?> clazz = Class.forName("com.dyit.classloader.Car");
何时加载class文件:
- new Car();
- Class.forName(“包.类”);
谁来加载Car.class: 类加载器
- Bootstrap 类加载器
- Extension 类加载器
- Application 类加载器
app–>继承—>ext–>继承–>-bootstrap
双亲委托机制:
Car.class--->加载(App)-->Ext(检查)-->Bootstrap
-
/* * 类加载器之间关系 */ System.out.println(clazz.getClassLoader()); System.out.println(clazz.getClassLoader().getParent()); System.out.println(clazz.getClassLoader().getParent().getParent());
1.1.2 链接: class文件内容合法
- 验证: 0xCAFEBABE
- 准备: 类变量(static)分配内存空间-方法区,初始化
class A{
static int x = 3; --->分配static内存 x=0;
}
- 解析
1.1.3 初始化,对类中的定义的属性进行初始化
x = 3;
1.1.4 使用
1.1.5 卸载
2.反射
2.1 反射概述
(反射的基本作用,关键?)
- 反射是在运行时获取类的字节码文件对象:然后可以解析类中的全部成分
- 核心思想和关键:得到编译以后的class文件
2.2 反射获取类对象
之前: Car c = new Car( );
现在 : clazz.newInstance() —>创建对象
2.2.1 创建对象的四种方式
方式 | 举例 |
---|---|
new关键字 | new Car(); |
clone(Object 的方法) | c.clone() |
(反)序列化(Serialable) | ObjectInputStream/ObjectOutputStream |
反射Class对象 | clazz.newInstance(); |
2.3 反射获取构造器对象
getDeclaredConstructors()取得全部构造器,不分public还是private,存到集合里
getDeclaredConstructor()取得单个构造器
反射得到的构造器可以做什么?
- 还是创建对象
- 如果是非public的构造器,需要打开权限(暴力反射),然后创建对象:
setAccessible(boolean)
反射可以破坏封装性,私有的也可以执行。
/*
* 利用反射技术获取无参和有参构造器
*/
//第一步:获取类对象
Class b = Book.class;
//第二步:提取类中的全部构造器对象
Constructor[] constructors = b.getDeclaredConstructors();
//第三部:遍历构造器
for (Constructor constructor : constructors) {
System.out.println("构造器名称" + constructor.getName() + "构造器参数数量" + constructor.getParameterCount());
}
/*
* 调用无参和有参构造器实例化对象返回
*/
//无参
Book book = (Book) constructors[1].newInstance();
System.out.println(book);
//有参
Book book2 = (Book) constructors[0].newInstance(010,"asdd","asd","asdasd","dasdasd",120.0,new Date());
System.out.println(book2);
2.4 反射获取成员变量对象
getDeclaredFields()获取全部
getDeclaredField()获取单个
/*
* 利用反射技术获取成员变量
*/
Class b = Book.class;
Field [] fs = b.getDeclaredFields();
for (Field f : fs) {
System.out.println(f);
}
2.5 反射获取方法对象
getDeclaredMethods()获取全部
getDeclaredMethod()获取单个
反射,以前是对象调方法,反射之后是方法调对象,new Dog d = new Dog(); —> d.eat()—> method01.invoke(d);
/*
* 利用反射技术获取 所有 成员方法
*/
Class<?> b = Book.class;
Method[] method1 = b.getDeclaredMethods();
// method1.setAccessible(true);
for (Method method : method1) {
System.out.println("返回方法名称:"+method.getName()+"返回方法参数类型:"+method.getReturnType()+"返回方法参数个数:"+method.getParameterCount());
}
/*
* 利用反射技术获取 单个 成员方法
*/
Class<?> b = Book.class;
Method method1 = b.getDeclaredMethod("setTitle");
Method method2 = b.getDeclaredMethod("setTitle", String.class);
//
// System.out.println("返回方法名称:" + method1.getName() + "返回方法参数类型:" + method1.getReturnType() + "返回方法参数个数:"
// + method1.getParameterCount());
// System.out.println("返回方法名称:" + method2.getName() + "返回方法参数类型:" + method2.getReturnType() + "返回方法参数个数:"
// + method2.getParameterCount());
//暴力开权限
method1.setAccessible(true);
method2.setAccessible(true);
//注意方法如果没有结果,返回null
Book book =new Book();
Object result1 = method1.invoke(book);
Object result2 = method2.invoke(book,"Java进阶");
2.6 反射作用
1.可以再运行时得到一个累的全部成分然后操作
2.破坏封装性。
3.可以破坏泛型的约束性。(ArrayList< Integer>)
4.最重要的用途:做Java高级框架。