下面的心得只是根据这本书的案例和根据我自己角度和理解,如果你没看过可以和我一起学习,如果您看过这本书,发现我说的有不对地方请指出,共同学习!
第一课 :暂时先略过。以后补
第二课:对象与内存的控制
- 类变量和实例变量:如果初始化两个变量,这两个变量同为类变量或同为实例变量,那么在实例化时要注意实例化的顺序,
// 下面实例变量初始化,将提示非法向前引用
int first = second-1;
int second = 2;
// 下面类变量量初始化,将提示非法向前引用
static int third = four-1;
static int four = 4;
//下面正常状态
int six = seven-1;
static int seven = 7;
上面得粗体字是正常的状态,因为静态变量(类变量)的初始化总在实例变量初始化前。不懂的可以先记住,后面有详解。
类变量和实例变量的属性,通过名字可以就可以知道,实例变量只能通过类的实例对象去访问;类变量就是属于类,直接可以通过类去访问,虽然类变量也可以通过类实例化的对象去访问,但底层最后还是通过类去访问的。所以我个人认为如果直接用类去访问类变量要比通过实例化的类对象去访问类变量的效率要高一些。
实例变量的初始化时机:对于实例变量而言,它属于Java对象本身,每次创建java对象时都需要为实力变量分配存储空间,并执行初始化操作。从语法角度我们可以从三个角度初始化实例变量,如下:
定义实例变量时指定初始值
非静态初始化块中对实例变量指定初始化值
在构造器中对实例变量指定初始化值
其中第1种和第2种方式要早于第3种(在构造器中初始化),第1和2种初始化的方式地位是平等的,所以执行初始化顺序按照在源程序中排列的顺序相同。看下面的代码,试想一下你的结果?
class Cat{
String name;
public Cat(String string) {
System.out.println("执行构造器初始化");
this.name = string;
}
{
System.out.println("执行非静态代码块");
weight = 2.0;
}
//定义时指定初始值
double weight = 4.0;
public String toString() {
return "age="+name+",weight="+weight;
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("jiafei");
System.out.println(cat);
}
}
//执行结果如下:
// 执行非静态代码块
// 执行构造器初始化
// age=jiafei,weight=4.0
和你想的结果一样么?结果一样证明你比我强啊,我在这里有个疑惑:就是weight的初始化的代码块和直接初始化,定义在代码块后但没报错?其实看过这我才懂真正的原因。其实这两种方式前面说过是平等的地位,经过编译后他们都在构造器初始化的,对于类中的double weight = 4.0;实际分成2次执行步骤:
double weight;//创建java对象时系统为实例变量分配内存空间。
weight = 4.0//这条语句将会被提到java的构造器中执行
下面看看这个简单的例子,并用javap -c JavaToolTest命令查看编译的原理如下:
public class JavapToolTest {
int count = 11;
{
count = 22;
}
public JavapToolTest() {
System.out.println(count);
}
public JavapToolTest(String name) {
System.out.println(name);
}
}
对编译后的JavaToolTest.class运行
javap -c JavaToolTest则看到
D:\software>javap -c -classpath D:\software JavapToolTest
Compiled from "JavapToolTest.java"
public class JavapToolTest extends java.lang.Object{
int count;
public JavapToolTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 11
7: putfield #2; //Field count:I
10: aload_0
11: bipush 22
13: putfield #2; //Field count:I
16: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_0
20: getfield #2; //Field count:I
23: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
26: return
public JavapToolTest(java.lang.String);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 11
7: putfield #2; //Field count:I
10: aload_0
11: bipush 22
13: putfield #2; //Field count:I
16: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
23: return
}
上面的javap中的粗体表示实例变量都在每个构造器中初始化,而且总位于构造器中所有语句之前。
分享到:
相关推荐
对Java语言本身深入理解,掌握面向对象的编程思想,了解常用的设计模式,这些都是基本功。同时,需要对Java生态中的各种框架和技术进行学习,如Spring、Hibernate等。此外,还要有良好的编码习惯,代码的可读性和可...
以下是对这位阿里四年工作经验的Java程序员从业心得的详细解读: 1. **Java基础的重要性**:无论在哪个阶段,Java基础知识都是面试中的重点。从String对象的理解到设计模式的应用,程序员需要不断深化对Java内存...
《Java基础36讲》作为一本Java编程入门书籍,强调了学习Java基础知识的重要性,并由四川大学研究生学长根据自己学习Java的心得体会,编撰而成,旨在为零基础同学和非计算机专业同学提供自学材料。该书详细地介绍了...
毕竟,扎实的基本功才是长期发展的基石。 ### 45. 在每次学习结束时总结所学知识 通过总结归纳,可以加深对所学内容的理解,并巩固记忆。 ### 46. 记录学习过程中的笔记和心得 养成记录笔记的习惯,不仅有助于...
在编程的世界里,成为一名高手并非一朝一夕之功,而是需要不断学习、实践和积累经验的过程。"如何成为编程高手"这个主题涵盖了广泛的技能和知识领域,让我们一起深入探讨。 首先,掌握基础是关键。无论是Java、...