目录
一、java的内存分析
1.java的内存区域
二、静态static
静态属性
静态方法
类加载
什么是类加载?
什么是触发类加载?
一、java的内存分析
1.java的内存区域
java的内存区域有五个区域
i.堆区:存放new的对象、成员遍历、常量池(存储字符串常量)
ii.栈区:存放局部遍历
iii.方法区:calss资源、static资源,它优先于对象进行加载,相同的资源只维护一份
iv.寄存器:用于存放于线程有关的资源
v.本地方法区:用于存放第三方语言的资源
通过代码实例进行分析可得,一般先将class加载到内存---方法区,实例化对象的资源到堆区,将new空间赋值给引用遍历--栈区,给成员变量赋值---堆区
class Woman{
String name;//记住这里要有个成员属性
public void eat() {
System.out.println(name+"正在吃饭");
}
}
public class Test2 {
public static void main(String[] args) {
Woman woman = new Woman();//1.生成test2.class和woman.class文件
woman.name="小明";
woman.eat();
}
}
二、静态static
静态属性
在这里我们要先对比静态属性与成员属性的区别
存储位置:成员属性存储在堆区,静态属性存储在方法区
调用方式:成员属性是对象调属性,静态属性是类调用静态属性
加载顺序:静态属性优先于成员属性进行加载
下面的代码示例说明,当我们实例化多个对象时,每个对象都有独立的成员属性,但是共享同一份静态属性
class Boy{
//String name;
static String name;//静态变量与成员变量不能同时写在这,会报错
public void wash() {
System.out.println("男朋友"+name+"正在帮我洗衣服");
}
}
public class Test1 {
public static void main(String[] args) {
Boy pyy = new Boy();//注意这里有个易错点,这里的创建空间有问题
//pyy.name="彭于晏";
Boy.name="彭于晏";
Boy wyz = new Boy();
//wyz.name="吴彦祖";//牢牢记住这里有个知识点,命名规则
Boy.name="吴彦祖";//静态属性属于类,推荐用类名调
//pyy.wash();
wyz.wash();
}
}
上面的案例说明了另一个情况,虽然静态属性可以在面向对象里面直接使用,但是它的应用场景大概有两种,一是共享资源时使用,二是作为状态值时使用
场景1:共享资源时使用
//静态属性的应用场景:共享资源时使用,统计一个类的对象被创建过多少次
class A{
static int count=0;
public A() {
count++;
}
}
public class Test2 {
public static void main(String[] args) {
new A();
new A();
new A();
System.out.println("A类被实例化了"+A.count+"次");
}
}
场景2:状态值时使用
//静态属性作为状态值使用的案例
//状态值:就是静态常量——
public class Test3 {
static final int HTTP_OK = 200;
static final int HTTP_ERROR = 404;
public static void main(String[] args) {
int state = getPageState();
if(state==HTTP_OK) {
System.out.println("返回页面成功");
}else if(state==HTTP_ERROR){
System.out.println("失败的页面状态");
}
}
private static int getPageState() {
return HTTP_OK;
}
}
静态方法
在成员方法的前面加入static修饰变为静态方法,注意在成员方法中可以使用静态属性,在静态方法中不能使用成员属性
应用场景:一般静态方法常常用于工具类中,在工具类中的静态方法我们可以直接使用类名区调用,可以在整个项目中使用
注意事项:静态方法可以抽取到工具类中共享,静态方法中不能使用this与super,静态方法不能被重写,静态方法可以被继承但不能重写
class A{
String name;
static int age;
public void test() {
System.out.println(age);
}
public static void staticTest() {
System.out.println(age);
}
}
public class Test1 {
public static void main(String[] args) {
new A().test();
A.staticTest();
}
}
类加载
什么是类加载?
类加载是指找到class文件,可以获取到文件中的所有资源,包名、类名、属性、方法以及构造器等
什么是触发类加载?
实例化对象、实例化子类对象、静态属性以及静态方法以及使用Class.forName(全限定名)--反射
代码示例
class A{
String name = "占山";
{
System.out.println(name);//这里写上面的name,因为已经赋值好了
}
public A() {//构造方法这里可以不用加{}
System.out.println("动态构造方法");
}
}
public class Test1 {
public static void main(String[] args) {
new A();
new A();
}
}
class A2{
static String name="占山";
static {
System.out.println(name);
System.out.println("静态代码块");
}
}
public class Test2 {
public static void main(String[] args) {
new A2();
new A2();//实例化多次对象,只触发一次
}
}
class AA{
String name = "成员属性";
static String name2 = "静态属性";
static{
System.out.println(name2);//静态代码块
System.out.println("静态代码块");
}
public AA(){
System.out.println("动态构造方法");
}
{
System.out.println(name);
}
}
public class Test3 {
public static void main(String[] args) {
new AA();
System.out.println("----");
new AA();
}
}
class AAA{
String name = "父类成员属性";
static String name2 = "父类静态属性";
static{
System.out.println(name2);//静态代码块
System.out.println("父类静态代码块");
}
public AAA(){
System.out.println("父类动态构造方法");
}
{
System.out.println(name);
}
}
class B extends AA{
String name = "子类成员属性";
static String name3 = "子类静态属性";
{
System.out.println(name);
System.out.println("子类动态代码块");
}
static {
System.out.println(name3);
System.out.println("子类静态代码块");
}
}
public class Test4 {
public static void main(String[] args) {
new B();
System.out.println("----");
new B();
}
}