Java内存
- 堆:存放new的对象和数组;可以被所有的线程共享,不会存放别的对象引用
- 栈:存放基本变量类型(会包含这个基本类型的具体数值);引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区:可以被所有的线程共享;包含了所有的class和static变量
类加载
当程序使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的链接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也会把这三个步骤统称为类加载或者类初始化。
- 类的加载:
- 就是指将class文件读入内存,并为之创建一个java.lang.Class对象
- 任何类被使用时,系统都会为之建立一个java.lang.Class对象
- 类的链接:
- 验证阶段:用于检验被加载的类是否具有正确的内部结构,并和其他类协调一致
- 准备阶段:负责为类的类变量分配内存,并设置默认初始化值
- 解析阶段:将类的二进制数据中的符号引用替换为直接引用
- 类的初始化:
- 在该阶段主要就是对类变量进行初始化
- 初始化步骤
- 假如还未被加载和连接,则程序先加载并连接该类
- 假如该类的直接父类还未被初始化,则先初始化其直接父类(在执行这个步骤的时候,系统对直接父类的初始化也遵循初始化步骤1-3)
- 假如类中有初始化造句,则系统依次执行这些初始化语句
- 初始化时机
- 创建类的实例
- 调用类的方法
- 访问类或者接口的类变量,或者为该类变量赋值
- 使用反射方式来强制创建某个类或者接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类 ```java public class Demo { public static void main(String[] args) { A a = new A() ; System.out.println(A.m); } } class A{ static{ System.out.println(“A类静态代码初始化”); m = 300 ; } static int m = 100 ; public A(){ System.out.println(“A类无参构造初始化”); } }
运行结果: A类静态代码初始化 A类无参构造初始化 100
Process finished with exit code 0
<a name="ICIwA"></a>
### 类加载器
- 作用:负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象;虽然我们不用过分关心类加载机制,但是了解这个机制可以更好的理解程序的运行
- JVM类加载机制
- 全盘负责:就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由类加载器负责载入,除非显示使用另外一个类加载来载入
- 父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类。
- 缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器先从缓存区中搜索该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存储到缓存区。
- 类加载器:
- ClassLoader:是负责加载类的对象
- Java运行时具有以下内置类加载器:
- Bootstrap class loader:他是虚拟机的内置类加载器,通常表示为null,并且没有父null
- Platform class loader :平台类加载器可以看到所有平台类,平台类包括由平台类加载器或者其祖先定义的Java SE平台API,其实现类和JDK特定的运行时类。
- System class loader:它也被称为应用程序类加载器,与平台类加载器不同。系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类。
- 类加载器的继承关系:System的父加载器为Platform,而Platform的父加载器为Bootstrap
- ClassLoader中的两个方法:
- static ClassLoader getSystemLoader():返回用于委派的系统类加载器
- ClassLoader getParent:返回父类加载器进行委派
```java
public class Demo {
public static void main(String[] args) {
ClassLoader c = ClassLoader.getSystemClassLoader();
System.out.println(c);
ClassLoader c1 = c.getParent();
System.out.println(c1);
ClassLoader c2 = c1.getParent() ;
System.out.println(c2);
}
}
运行结果:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1b6d3586
null
Process finished with exit code 0
反射概述
是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行时期仍可以扩展
获取Class类的对象
我们要通过反射去使用一个类,首先我们要获取到类的字节码文件对象,也就是类型为Class类型的对象,提供三种方式获取Class类型对象:
- 使用类的class属性来获取对应的Class对象。例:Student.class 将会返回Student类对应的Class对象
- 调用对象的getClass()方法,返回该对象所属类对应的Class对象,该方法是Object类中的方法,所有的Java对象都可以调用方法。
- 使用class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名路径。 ```java 建一个Student类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
Class
Student student = new Student() ;
Class<?extends Student> c2 = student.getClass() ;
System.out.println(c2);
Class<?> c3 = Class.forName("com.bai.Student");
System.out.println(c3);
}
} 运行结果: class com.bai.Student class com.bai.Student class com.bai.Student
Process finished with exit code 0
<a name="pLGxy"></a>
### 获取成员变量并使用
- Class类中用于获取成员变量的方法
- **_Field[] getFields()_** 返回素有公共成员变量对象的数组
- **_Field[] getDeclaredFields()_** 返回所有成员变量对象的数组
- **_Field getField(String name)_** 返回单个公共成员变量对象
- **_Field getDeclaredField(String name)_** 返回单个成员变量对象
- File类中用于给成员变量赋值的方法
- **_void set(Object obj,Object value_** 给obj对象的成员变量赋值为value
```java
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> c = Class.forName("com.bai.Student") ;
Constructor<?> con = c.getConstructor() ;
Object obj = con.newInstance() ;
Field name = c.getDeclaredField("name");
Field age = c.getDeclaredField("age") ;
Field address = c.getDeclaredField("address") ;
name.setAccessible(true); //取消访问检查,可以访问私有方法
name.set(obj,"小黑") ;
age.set(obj,23) ;
address.set(obj,"sdsds");
System.out.println(obj);
}
}
*************************************************************************************
public class Student {
private String name ;
int age ;
public String address ;
public Student() { }
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
private Student(String name){ this.name = name ; }
private Student(int age){ 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; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
获取成员方法并使用
- Class类中用于获取成员方法的方法
- Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的
- Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的。
- Method getMethod(String name,Class<?>…parameterTypes) 返回单个公共成员方法对象
- Method getDeclaredMethod(String name,Class<?>…paremeterTypes) 返回单个成员方法对象。
- Method类中用于调用成员方法的方法
- Object invoke(Object obj,Object…args) 调用obj对象的成员方法,参数是args,返回值是Object类型 ```java import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
public class Demo { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class<?> c = Class.forName(“com.bai.Student”) ; Method[] methods = c.getDeclaredMethods() ; for(Method method : methods){ System.out.println(method); } Constructor<?> con = c.getConstructor() ; Object obj = con.newInstance(); Method m1 = c.getMethod(“method1”) ; m1.invoke(obj) ;
Method m2 = c.getMethod("method2", String.class);
m2.invoke(obj,"大四的") ;
Method m3 = c.getMethod("method3", String.class, int.class);
System.out.println(m3.invoke(obj,"是滴撒",55));
Method f = c.getDeclaredMethod("function");
f.setAccessible(true); //取消访问检查,可以访问私有方法
f.invoke(obj) ;
}
}
public class Student { private String name ; int age ; public String address ; public Student() { } public Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
private Student(String name){ this.name = name ; }
private Student(int age){ 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; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
private void function(){ System.out.println("function"); }
public void method1(){ System.out.println("method"); }
public void method2(String s){ System.out.println("method"+s); }
public String method3(String s,int i){ return s+","+i ; }
}
```java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
test1();
test2();
test3();
}
public static void test1(){
Student student = new Student() ;
long startTime = System.currentTimeMillis() ;
for(int i=0;i<1000000000;i++){
student.getAge() ;
}
long endTime = System.currentTimeMillis() ;
System.out.println("普通方法执行时间-->"+(endTime-startTime)+"ms");
}
public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Student student = new Student() ;
Class c = student.getClass() ;
Method getAge = c.getDeclaredMethod("getAge") ;
long startTime = System.currentTimeMillis() ;
for(int i=0;i<1000000000;i++){
getAge.invoke(student) ;
}
long endTime = System.currentTimeMillis() ;
System.out.println("反射执行方法执行时间-->"+(endTime-startTime)+"ms");
}
public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Student student = new Student() ;
Class c = student.getClass() ;
Method getAge = c.getDeclaredMethod("getAge");
getAge.setAccessible(true); //取消访问检查,可以访问私有方法
long startTime = System.currentTimeMillis() ;
for(int i=0;i<1000000000;i++){
getAge.invoke(student) ;
}
long endTime = System.currentTimeMillis() ;
System.out.println("反射关闭检测执行时间-->"+(endTime-startTime)+"ms");
}
}
运行结果:
普通方法执行时间-->6ms
反射执行方法执行时间-->3538ms
反射关闭检测执行时间-->2290ms
Process finished with exit code 0 那就
获取构造方法并使用
- Class类中用于获取构造方法的方法
- Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组
- Constructor<?>[] getDeclaredConstructor() 返回所有构造方法对象数组
- Constructor
getConstructor(Class<?>…parameterTypes) 返回单个公共构造方法对象。(参数:要获取的构造方法的参数个数和数据类型对应的字节码文件对象) - Constructor
getDeclaredConstructor(Class<?>…parameterTypes) 返回单个构造方法对象
- Constructor类中用于创建对象的方法
- T newInstance(Object…initargs) 根据指定的构造方法创建对象 ```java import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException;
public class Demo { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException { Class<?> c = Class.forName(“com.bai.Student”) ; Constructor<?>[] cons = c.getDeclaredConstructors() ; for(Constructor con : cons){ System.out.println(con); } } }
public class Student { private String name ; int age ; public String address ; public Student() { } public Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } private Student(String name){ this.name = name ; } private Student(int age){ 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; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
```java
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException {
Class<?> c = Class.forName("com.bai.Student") ;
Constructor<?>[] cons = c.getDeclaredConstructors() ;
for(Constructor con : cons){
System.out.println(con);
}
System.out.println("-------------------------");
Constructor<?> con1 = c.getConstructor() ;
System.out.println(con1);
Object obj = con1.newInstance() ;
System.out.println(obj);
System.out.println("-------------------------");
Constructor<?> con2 = c.getDeclaredConstructor(String.class) ;
con2.setAccessible(true); //取消访问检查,可以访问私有方法
Object obj1 = con2.newInstance("小黑");
System.out.println(obj1);
}
}
************************************************************************************
public class Student {
private String name ;
int age ;
public String address ;
public Student() { }
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
private Student(String name){ this.name = name ; }
private Student(int age){ 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; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}