// 实验代码
package test1;
public class ClassFlow {
int a;
static String bstring;
static {System.out.println("this is ClassFlow 静态代码块!");}
public ClassFlow(int a,String bstring){
this.a = a;
this.bstring = bstring;
System.out.println("this is ClassFlow "+this.a+this.bstring);
}
public void show1(int a){
System.out.println("this is show1 int :" +a);
}
public static void show2(int c){
System.out.println("this is show int "+c);
}
public static void main(String[] args){
ClassFlow classFlow = new ClassFlow(3,"sss");
classFlow.show1(1);
ClassFlow.show2(2);
}
}
this is ClassFlow 静态代码块! this is ClassFlow 3sss this is show1 int :1 this is show int 2
图片:
先看代码。
public class Test3 {
static class Test{
static ObjectHolder staticObj = new ObjectHolder();
ObjectHolder instanceObj = new ObjectHolder();
void foo(){
ObjectHolder localObj = new ObjectHolder();
System.out.println("done");
}
}
private static class ObjectHolder{};
public static void main(String[] args){
Test test = new Test3.Test();
test.foo();
}
}
staticObj、instanceObj、localObj 这三个变量本身(不是他们所指的对象)存放的地方。
staticObj随着Test的类型信息存放在方法区,
instanceObj随着Test的对象实例存放在java堆中,
localObj则是存放在foo()函数方法帧的局部变量表中。
简单理解就是:
1、staticObj是静态变量所以在会和类一起存放到方法区中(更详细的就是方法区中的静态区(静态域))。
2、instanceObj是实例变量,也就是说这个成员变量只有在类创创建实例的时候才会出现,
也就是new的时候在堆区中给这个类进行实例化分配内存的时候才会准确的出现并且还可以被使用。(如果不new的话)
在方法区的类内容区也会有这个变量,因为虚拟机加载类的 .class文件的时候类会被加载到方法区中
如果变量有初值的话在在方法区中的类内容区中的这个变量也会有初值的。总的来说就是如果是静态变量的话new后堆区中对应静态变量会存放一个地址
(这个地址指向方法区中的静态区的这个静态变量并给它赋值。)静态变量是同类中共同持有的。
3、localObj变量是在方法中的也就是只有用到这个方法的时候才会出现这个变量。这个方法在方法区中也存在。
流程:先从new这个类开始,new这个类的时候会在堆区中分配给这个类的所有方法,地址中会存一个指到方法区中对应这个类的方法。
new结束后到下一行代码,也就是到了test.foo();当执行到这一行的时候会去堆区中的这个类的地方找到
这个函数(这个函数也是一个地址,最终还是要到方法区中才找到完整的这个类的功能),
通过地址找到方法区中对应的函数然后回到栈区分配内存执行这个函数(这一段内存也叫栈帧),
执行到这个方法中的 ObjectHolder localObj = new ObjectHolder(); 就会在栈中创建这个变量并分配内存
(只是这个变量(这里一个类所以也可以叫做引用)不是这个变量后面的new ObjectHolder,
new ObjectHolder会到堆区中创建内存的)。最后执行打印。
(每一段代码只要是{}结束了就会释放在 栈中的内存,main函数到}的时候也会释放栈中的内存)
三、关于文档写java命令行执行
1、cd 进入.java文件所在的位置。
2、java 空格 -d(指定生成的.class文件在的目录)空格.(当前目录,这个地方要指明.java 文件的位置,因为我们进入了java文件在的目录所以直接点就可以了)文件名.java ---------------------- 就可以看到目录下会生成一个.class 文件,.class 用java 类名的话是默认当前目录的。如果包名是 per.wgc的话就会出现找不到主类的情况出现。用-d的用意在于如果是per.wgc这样的包名的话直接运行.class文件是不可以的,因为这种形式的包名要指定权限类名称。
3、java -cp(classpath) 指定包所在的目录 类的权限名称(eg:包名是per.wgc 类名是MyTest 所以应该是 per.wgc.MyTest)
静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块得以赋值,但不能访问这个变量。
下面展示 代码举例子。
public class Test{
static{
i = 0;//给变量赋值可以正常进行编译通过
System.out.println(i); // 这句编译不能正常通过,编译器会提示“非法前向引用。这里引用了变量 i 所以错误”
}
static int i = 1;
}
五、两个不同的类:
虚拟机中可以同时存在两个相同的类,原因是:一个是由虚拟机的应用程序类加载器所加载的,另外一个是由我们自定义的类加载器加载的,虽然量两个类都来自同一个.class文件但是在java虚拟机中仍然是两个独立的类,如果用instanceof检查得到的结果是false。
存在两种加载器一种是使用c++写的是java虚拟机的自身的一部分;另外一种就是其他所有的类加载器,这些类加载器都是有java语言实现,独立存在于虚拟机外部,并且全部继承自抽象类java.lang.ClassLoader。
以上是个人理解,可能存在错误。
2022-08-08
8
七月十一
壬寅年 虎
戊申月 癸巳日



