JavaSE Day21
JavaSE Day21 发射 类加载
目录
类加载
一个程序只能有一个main方法
类的生命周期

类的加载过程:加载、连接、初始化
把类的字节码文件 加载到 方法区的内存中。同时在堆内存中生成一个Class类型的类对象(此对象,相当于这个类的模板文件);
-
类的装载:查找和导入Class文件;
-
类的连接:把二进制数据 合并到JRE中;此过程分为三个步骤:
- 验证
验证字节码文件的格式。 - 准备
为类中的静态变量开辟空间,并且进行默认初始化; - 解析
把符号引用 替换成指针;
- 验证
-
初始化:对静态变量进行声明处或者静态块处初始化;
-
使用
-
卸载
类的初始化
- 当创建某个类的新实例时;
- 当调用某个类的静态成员;
- 当初始化某个子类时,该子类的所有父类会被初始化
- 当使用反射方法强制创建某个类或接口的对象时
- 当虚拟机java命令运行启动类(主方法所在的类),会加载主类;
注意:static final类型的变量,并且在编译期能够确定值的,是不会引起初始化的情况
类加载器
根类加载器
主要作用:
- 负责加载系统的核心类库
- Java/jre/lib目录下的所有类库
扩展类加载器
主要作用:加载 Java/jre/lib/ext目录下的所有类库
系统类(应用类)
主要作用:加载 classpath路径下的类 当前路径下的类
自定义类加载器(继承 ClassLoader类)
主要作用:加载自己路径下的类
加载器之间的关系
package day21;
public class Demo3 {
public static void main(String[] args) {
// 获得Demo3的类加载器
// AppClassLoader 系统类加载器(应用类记载器)
ClassLoader loader = Demo3.class.getClassLoader();
System.out.println(loader);
// ExtClassLoader 扩展类加载器
System.out.println(loader.getParent());
// null 根类加载器
System.out.println(loader.getParent().getParent());
}
}
加载类时用的是父类委托机制
使用类加载器的顺序
根加载器 <- 扩展类加载器 <- 系统类加载器 <- 用户类加载器
先找父类能加载就加载了并返回个对象(加载成功),父类不能加载就原路返回找子类 看能不能加载;
加载类的两种方式
package day21;
public class TestLoader1 {
public static void main(String[] args) throws ClassNotFoundException{
// 加载了类
ClassLoader.getSystemClassLoader().loadClass("day21.TestLoader1");
// ClassLoader.getSystemClassLoader().loadClass("day21.Demo4");
// 类的初始化
Class.forName("day21.Demo4");
// 类名 是否初始化,true表示要初始化 类加载器
Class.forName("day21.Demo4",true,ClassLoader.getSystemClassLoader());
}
}
要用用户类加载器,说明java文件的字节码文件不在classpath目录下;
package day21;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
class MyLoader extends ClassLoader{
String path;
MyLoader(String path){
this.path = path;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class c = null;
// d:/data1/Hello.class
// path -> d:/data/ name -> Hello
path = path+name.concat(".class");
File f = new File(path);
FileInputStream fin = null;
try {
fin = new FileInputStream(f);
byte[] b = new byte[fin.available()];
int len = fin.read(b);
// 解析成方法区能够识别的数据结构
c = this.defineClass("Hello", b, 0, len);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(fin != null){
try {
fin.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return c;
}
}
public class TestMyLoader {
public static void main(String[] args) throws ClassNotFoundException {
// d:data1/Hello.class
MyLoader loader = new MyLoader("d:/data1/");
Class.forName("Hello",true,loader);
}
}
安全管理器
重写SecurityManager来控制我的程序的安全性;
package day21;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
// 自定义安全管理器
class MySecurity extends SecurityManager{
@Override
public void checkRead(String file) {
// TODO Auto-generated method stub
if(file.endsWith(".java")){
throw new SecurityException("不允许读java文件");
}
}
}
public class TestFileInputStream {
public static void main(String[] args) throws IOException {
// 设置自己的安全管理器
System.setSecurityManager(new MySecurity());
File f = new File("d:/data1/Hello.java");
FileInputStream fin = new FileInputStream(f);
int temp = fin.read();
System.out.println((char)temp);
fin.close();
}
}
反射
(在运行期)动态的获得类(字节码文件中)中的数据;
加载类的三种方法
// 获得字节文件对应的对象
// 1.
// Class<Person> c = Person.class;
// 2. 匹配上限类 和 上限类的子类
// Class<? extends Person> c = new Person().getClass();
// 3.
Class<?> c = Class.forName("day21.Person");
获得属性
Field属性
- getFields 获得所有属性,但是是共有的
- getDeclaredFields() 获得所有属性,包括私有的;
- getDeclaredField(属性名) 获得单个属性
- Set()给属性赋值
- Get(对象) 获得属性的值
获得方法:
Method属性
- getDeclaredmethods() 获得所有方法
- getDeclaredMehtod(方法名,参数类型列表) 获得单个方法
- invoke(对象,实参列表) 调用方法
获得构造器
Constructor属性
- getDeclaredConstructors();获得所有构造器
- getDeclaredConstructor(参数类型列表):获得单个构造
- newInstance(实参列表) 调用构造器
实例
package day21;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
class Person{
private int no;
public String name;
public Person(){
System.out.println("无参构造");
}
public Person(int no,String name){
this.no = no;
this.name = name;
System.out.println("带参构造:"+this.no+","+this.name);
}
public void show(){
System.out.println("无参方法show");
}
public String disp(int n,String str){
return "带参方法"+n +str;
}
}
public class TestPerson {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
// 从字节码文件获得信息
// 获得字节文件对应的对象
// 1.
// Class<Person> c = Person.class;
// 2. 匹配上限类 和 上限类的子类
// Class<? extends Person> c = new Person().getClass();
// 3.
Class<?> c = Class.forName("day21.Person");
// ---------获得属性-----------------
// Field[] fs = c.getFields();// 共有的
Field[] fs = c.getDeclaredFields();//全部属性
for(Field f:fs){
System.out.println(f.getName());
System.out.println(f.getType());
System.out.println(Modifier.toString(f.getModifiers()));// 访问权限
}
//设置 安全管理器
// System.setSecurityManager(new SecurityManager());
// 获得单个属性
Field f = c.getDeclaredField("no");
f.setAccessible(true);// 破坏封装,设置访问权限;为true表示能修改私有属性;
Object obj = c.newInstance();
f.set(obj,22);
System.out.println(f.get(obj));
// -----------方法--------------
java.lang.reflect.Method[] ms = c.getDeclaredMethods();
for(java.lang.reflect.Method m : ms){
System.out.println(m.getName());
System.out.println(m.getReturnType());
System.out.println(Arrays.toString(m.getParameters()));
}
// 无参就不用写参数
java.lang.reflect.Method m1 = c.getDeclaredMethod("show");
m1.invoke(obj);
java.lang.reflect.Method m2 = c.getDeclaredMethod("disp", int.class,String.class);
String str = (String) m2.invoke(obj,123,"abc");
System.out.println(str);
// ----------------获得构造器------------------
System.out.println("构造器");
Constructor[] crs = c.getDeclaredConstructors();
for(Constructor cr:crs){
System.out.println(cr.getName());
System.out.println(Arrays.toString(cr.getParameters()));
}
Constructor cr1 = c.getDeclaredConstructor();
cr1.newInstance();
Constructor cr2 = c.getDeclaredConstructor(int.class,String.class);
cr2.newInstance(11,"Tom");
}
}
注解
注解的概念和作用;
作用是给编译器提供信息;
JDK中提供的标准注解;
@Override@Depredcated已过时的;@Suppresswarnings镇压警告;- All 镇压所有警告
- Rawtypes
- Unchecked
- Unused
- Serial 序列化 版本号的镇压警告;
@FunctionalInterface
package day21;
import java.util.ArrayList;
import java.util.List;
class Parent{
int x;
@Deprecated
public void sf(){}
public void f(){
int n = 34;
System.out.println(n);
}
}
class DemoA{
@SuppressWarnings("unchecked")
public void show(){
@SuppressWarnings({"rawtypes","unused"})
List list = new ArrayList();
list.add("abc");
list.add(123);
}
}
class Child extends Parent{
// 注解 作用是给编译器提供信息;
@Override
public void f() {
// TODO Auto-generated method stub
super.f();
}
}
public class TestAnno1 {
public static void main(String[] args) {
Person s = new Person();
}
}
JDK的元注解
在定义注解时,需要确定注解修饰的类型、运行的范围等参数,就需要元注解来修饰自定义注解;
@Target
修饰哪些程序元素
- CONSTRUCTOR 构造方法声明
- FIELD 字段声明(包括枚举常量)
- LOCAL_VARIABLE 局部变量声明
- MERHOD 方法声明
- PACKAGE 包声明
- PARAMETER 参数声明
- TYPE 类、接口(包括注释类型)或枚举声明
@Rentention
注解保留时间;
- RetentionPolicy.SOURCE 源代码
- RetentionPolicy.CLASS 默认 字节码
- RetentionPolicy.RUNTIME 运行时,一般是给反射使用
@Inherited
继承性说明
指定被修饰的Annotation将具有继承性, 如果某个类使用了某个注解,则其子类将自动被某个注解修饰
@Documented
文档类注解
自定义注解
@interface 注解名{
访问修饰符 类型 成员名()[ default 默认值];
}
注解解析
package day21;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.lang.annotation.*;
@Target(ElementType.TYPE)// 范围
@Retention(RetentionPolicy.RUNTIME)// 什么时候
@Inherited // 继承
@Documented
@interface FuitAnno{
// 只有一个成员时,用value作为方法名
public String value() default "Apple";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ColorAnno{
public Color color() default Color.RED;
}
@FuitAnno(value="orange")
class Fuit{
public String name;
}
enum Color{
RED,GREEN,YELLOW;
}
class Apple extends Fuit{
int size;
// 颜色
@ColorAnno(color = Color.YELLOW)
Color colorName;
}
public class TestAnno {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
// 反射的技术 获得注解的信息
// Fuit注解信息
Class<?> c1 = Class.forName("day21.Fuit");
Annotation[] ans = c1.getDeclaredAnnotations();
Arrays.stream(ans).forEach(System.out::println);
// Apple
Class<?> c2 = Class.forName("day21.Apple");
// 获得子类 继承父类的类型上的注解信息;
Annotation[] ans1 = c2.getAnnotations();
Arrays.stream(ans1).forEach(System.out::println);
// 获得属性上的注解信息
Annotation[] ans2 = c2.getDeclaredField("colorName").getAnnotations();
Arrays.stream(ans2).forEach(System.out::println);
}
}


浙公网安备 33010602011771号