[敏捷JAVA读书笔记-java基础部分] 第四章

一、类变量和类方法


对象是由属性和行为构成,属性对应java类中的 成员变量(实例变量和类变量),行为对应类中的方法。

java类的状态是由他的成员变量的状态决定的。

在java中被声明为static的成员变量和成员方法是类变量和类方法,在类加载的时候即被初始化。存放在方法区。

没有被声明为static的成员变量和成员方法是实例变量和实例方法。实例变量在new 一个对象的时候初始化。实例方法应该是啥时候调用,啥时候初始化。

实例变量存放在堆区,他的生命周期与对象的相同。调用实例方法的时候,虚拟机会在栈区开辟一块单独的内存空间,所以实例方法内的变量是现成安全的,执行完毕后,虚拟机会收回这块内存。


二、更多初始化的内容


执行一个类的时候,jvm首先找到类名.class,然后装载,加载进内存,这个时候在内存中会形成一个 类对象,用来代表这个类(所以我们用对象.class.getClassName()的时候总是得到相同的值,这个就是类对象的名字),然后进行静态初始化,初始化类中的所有成员变量以及成员函数还有static块。
静态初始化只进行一次:当静态变量或者方法被调用,类加载的时候进行!静态的东西是属于类的。而不是属于对象的,过度的使用静态是很危险的!确信使用静态的时候才使用静态!

java初始化的时候一个基本的原则:
先静态后动态
先定义初始化后构造函数。
package com;

class A{
A(String who){
System.out.println("create A by "+who);
}
}

class B{
A a = new A("B");

B(String who){
System.out.println("create B by "+who);
}
}

class C{
static {
A a = new A("C static");
}

C(String who){
System.out.println("create C by "+who);
}
}

class Init{

static B b = new B("Init");
static C c = new C("Init");
//C c = new C("Init");

public static void main(String [] args){

}
}
保存为Init.java
编译:javac com/Init.java
执行:java com/Init

当你在cmd命令行窗口上敲入 java com/Init 的时候,
1、启动java虚拟机。
2、到com下面查找Init.class。
3、如果有就加载进jvm,没有就跑出一个nofound的异常。
4、jvm将Init.class加载到内存,形成类对象,然后开始静态初始化。执行 static B b = new B("Init");
5、然后加载B.class进内存
6、然后执行new B("Init");的操作。即调用B的构造函数。
7、根据先定义初始化后构造函数的顺序,会先执行 A a = new A("B");
8、jvm加载A进内存,并形成A的类对象。然后调用A的构造函数创建A 。
9、然后调用B的构造函数创建B。
10、然后执行 static C c = new C("Init");,重复上面的顺序。
所以最后的打印结果是:
create A by B
create B by Init
create A by C static
create C by Init

注意:如果把 static C c = new C("Init");改成:C c = new C("Init");打印的结果应该是:
create A by B
create B by Init

因为我们并没有用调用C的构造函数去new一个C出来,而没有static修饰的变量不是类变量,并不在类加载的时候初始化,他是在调用此类的构造函数之前被初始化。

再来看一个java中比较有趣的东西:

package com;

class Some{
int i;

boolean b;

char c;

double d;

int k = f();

int u = g(k);

{
Init init = new Init();
}

int f(){
return 10;
}

int g(int u){
if(u==10)
return 100;
return 0;
}

void print(){
System.out.println("i:"+i+" k:"+k +" u:"+u+" b:"+b+" c:"+c+" d:"+d);
if(c=='\0'){
System.out.println("c is '\0'");
}
}
public static void main(String [] args){
Some some = new Some();
some.print();
}
}

执行结果是:

create A by B
create B by Init
create A by C static
create C by Init
i:0 k:10 u:100 b:false c: d:0.0
c is ' '

java允许在定义初始化的时候调用函数。
也允许使用{}这样的东西来做一些特别的事情。

三、new String("a string")到底干了什么?

String str = new String("a string");到底做了什么?

1、an object of String is create //在堆区内创建一个String类型的对象
2、the object is initialized by "a string"//用a string 初始化它
3、a variable as handle to String is create //在栈区内创建一个句柄,也就是引用变量str
4、the value of the handle variable is assign to the object//这个str指向堆区内的String对象

四、传值还是传引用

java中函数传递参数统统可以理解为是传值!不过要搞清楚,这个值里面是什么东西,是对象的引用还是基本的数据类型。

class Letter{
char c = 'a';
}
class passObject{
static void f(Letter y){
y.c = 'z';// y.c = 'z' 就是改变这个对象的成员变量c的值,所以,x.c = ‘z’
}
public static void main(String [] args){
Letter x = new Letter();//创建一个Letter类型的变量x,x中存储Letter对象的首地址比如0x001....
f(x);//相当于做了 y = x的操作,这个时候y与x指向同一个对象

System.out.println(x.c);
}
}
x是一个引用,他是Letter类型的变量,他存储Letter的对象的首地址比如可能是0x001(也就是他是指向Letter对象的句柄),这句话就是把对象的引用付给y 就相当于做了 y = x 操作,这个时候y与x指向同一个对象。

你可能感兴趣的:([敏捷JAVA读书笔记-java基础部分] 第四章)