执行流程
While{}do 和do{}while
do{}while(flag) 至少会执行一次,而while(flag){} do 会根据条件判断
for
//这是一个无线循环
for(;;){
}
逗号操作符 可以用逗号分割一系列的语句,语句会独立,他们的类型必须相同.
标签: 用于迭代语句中(唯一的使用场景)例如:
public class ConditionTest {
public static void main(String[] args) {
out:
for (int x = 0; x < 100; x++) {
inner:
for (; x < 4; x++) {
if (x == 3) {
break inner;
}
System.out.println("inner" + x);
}
System.out.println(x);
if (x == 4) {
break out;
}
}
}
}
//---output
inner0
inner1
inner2
3
4
Process finished with exit code 0
5.1构造函数确保初始化
注意,因为构造函数必须和类名一致,所以每个方法首字母小写的规则不适合构造函数.构造器是一种特殊的方法,因为他没有返回值.
区分重载的方法只能是参数类型不同,或者参数数量不同.不能通过返回值不同来区分重载.
5.3默认构造器
如果类中没有写任何构造器,编译器会自动生成一个无参构造器,如果类中包含任何参数的构造器,编译器是不会生成无参构造器.(因为这时候编译器会认为你是故意不需要默认构造器)
5.4this关键字
构造器中调用构造器.可以用this,表示符合参数条件的构造函数.
Static 的含义:
因为static 意思就是不没有this对象,所以他不能调用其他非静态方法.因为他无法向对象发送消息,只有对象才能发消息.但是可以通过传引用参数,让引用参数去调用他自身的方法.如果在代码中大量出现static方法,就需要重新考虑自己的设计了.
5.5清理:终结处理和回收
对于某些对象可能不是调用new 获取了一块特殊空间,由于垃圾回收器只知道回收new 分配的内存,所以对这部分特殊的空间,垃圾回收器是无法释放的.这个时候类可以override finalize(),Object在回收前会触发,垃圾回收器会调用对象的 finalize(),在下次回收的时候便可以真正释放.所以可以在finalize()里做一些清理工作.
需要明白:
1.对象可能不被垃圾回收
2.垃圾回收并不等于析构
所以finalize() 里面的做的清理工作,有可能在你离开界面的时候不被调用,也有可能在这一时刻被调用.如果需要很严格的确保离开界面被释放对象,需要手动创建一个执行清理的方法.
5.5.1 finalize 用途何在?
不应该将finalize 作为通用的清理方法.
记住:垃圾回收只与内存有关.
一般在调用其他非java代码创建的对象,java垃圾回收器无法释放内存,比如 调用 本地jni /c/c++ 调用了malloc 系列分配的存储空间,除非调用了free() 函数,否则存储空间将无法得到释放,从而造成内存泄露.当然free()是c/c++的函数,需要用本地方法调用.
可以通过在finalize(){ }做一些对象测试,看看某些很难跟踪的成员有没有及时在该对象释放前做变动.通常是解决一些疑难问题.
java内存回收的方案:"自适应,分代,mark-copy,mark-sweep"的 自适应,就是会自动检视当前堆空间处于什么状态,如果是所有对象都相对稳定,垃圾回收器效率比较低,就切换到mark-sweep(标记-清除),如果碎片比较多,自动切换到Copying(停止-复制);分代在新生代 采用停止-复制算法,在老年代 采用mark-sweep算法.
jvm中有一些提升速度的附加技术.有一种叫JIT(just-in-time)这个技术可以把程序全部或者部分翻译成本地机器码, 代替JVM的工作(这部分工作本来是JVM来操作的).虚拟机要执行某个类的代码,先加载class 文件,然后装进内存中.在这部的时候按理需要进行把程序翻译成本地机器码执行.通过采用JIT技术 可以使用惰性评估(lazy evaluation)在必要时才编译代码,从而可以使得部分不会被执行的代码无需编译,达到提高运行速度.Java hotSpot用到了这技术.
5.6成员初始化
java在成员变量中会进行默认初始化,但是在局部函数里面是不会自动默认初始化变量的,如果在局部函数中需要用到没有初始化的局部变量,编译器是无法编译通过的.
在给变量赋值的时候可以直接把函数值赋予变量,也可以把已经存在的变量当做参数,传给函数,再次赋值给其他变量.但是如果是通过调用函数并且传递另一个变量作为参数时,需要确保该参数的初始化要在调用之前.
public class IniteTest {
int i = f();
int j = g(i);
private int f() {
return 0;
}
private int g(int g) {
return g;
}
public static void main(String[] args) {
}
}
如果需要用到的变量在需要调用函数之后则无法正常编译.
public class IniteTest {
int j = g(i);
int i = f();
private int f() {
return 0;
}
private int g(int g) {
return g;
}
public static void main(String[] args) {
}
}
//output
IniteTest.java:9: 错误: 非法前向引用
int j = g(i);
^
1个错误
5.7构造器初始化
成员变量自动初始化,会在构造器初始化变量之前发生.
在类内部,变量的定义顺序决定了初始化的顺序.(也就是说变量初始化顺序只跟,变量在类中定义的顺序有关,变量初始化,会优先构造函数里面调用,而方法的定义只有在第一次调用是才会被初始化)
/**
* Created by leon on 17-12-13.
*/
class Window {
public Window(int seq) {
System.out.println("window" + seq);
}
}
class House {
Window w1 = new Window(1); //---①
void f() {
System.out.println("f()"); //---⑤
}
House() {
System.out.println("开始进入构造函数");
w3 = new Window(3); //---④
}
Window w2 = new Window(2); //---②
Window w3 = new Window(3); //---③
}
public class inilationOrder {
public static void main(String[] args) {
House house = new House();
house.f();
}
}
//output---
window1
window2
window3
开始进入构造函数
window3
f()
5.7.2静态数据的初始化
无论创建多少个对象,静态数据都只占一份存储区域.就是在方法区,不是在垃圾回收器的堆中.static 不能应用与局部变量,他只能作用于域.因为局部变量是存放在栈中.
/**
* Created by leon on 17-12-13.
*/
class Bowl {
Bowl(int marker) {
System.out.println("Bowl " + marker);
}
void f1(int marker) {
System.out.println("f1 maker" + marker);
}
}
class Table {
static Bowl bowl = new Bowl(1);
Table() {
System.out.println("Table 构造函数");
bowl2.f1(1);
}
void f2(int maker) {
System.out.println("f2 maker" + maker);
}
static Bowl bowl2 = new Bowl(2);
}
class Cupboad {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboad() {
System.out.println("Cupboad构造函数");
bowl4.f1(2);
}
void f3(int maker) {
System.out.println("f3 maker" + maker);
}
static Bowl bowl5 = new Bowl(5);
}
public class StaticInitionTest {
public static void main(String[] args) {
new Cupboad();
new Cupboad();
table.f2(1);
cupboad.f3(1);
}
static Table table = new Table();
static Cupboad cupboad = new Cupboad();
}
//output---
Bowl 1
Bowl 2
Table 构造函数
f1 maker1
Bowl 4
Bowl 5
Bowl 3
Cupboad构造函数
f1 maker2
Bowl 3
Cupboad构造函数
f1 maker2
Bowl 3
Cupboad构造函数
f1 maker2
f2 maker1
f3 maker1
结果说明 :
1.静态成员变量不论创建多少个实例,都只会创建一次.静态变量不会再次被初始化
2.静态变量的初始化顺序要优先非静态成员变量的顺序
3.构造函数的顺序在成员变量之后
5.7.3 显示静态初始化(静态块/静态子句)
静态块看起来想一个方法,实际上是只是一段跟在 static 后面的代码,和其他静态化变量的初始化动作一样,这段代码只执行一次.①在首次生成这个对象时,②或则首次访问属于那个类的静态数据成员时.事实证明,只要调用一个类的任意一个静态变量,其他的所有的静态变量都会被初始化,包括静态块里面的.
class BlockBowl {
BlockBowl(int marker) {
System.out.println("Bowl " + marker);
}
void f1(int marker) {
System.out.println("f1 maker" + marker);
}
}
class BlockTable {
static BlockBowl bowl;
static BlockBowl bowl2;
static {
bowl = new BlockBowl(1);
bowl2 = new BlockBowl(2);
}
BlockTable() {
System.out.println("Table 构造函数");
bowl2.f1(1);
}
void f2(int maker) {
System.out.println("f2 maker" + maker);
}
BlockBowl bowl3 = new BlockBowl(3);
}
public class StaticBlockTest {
public static void main(String[] args) {
System.out.print(BlockTable.bowl);
}
}
//output-----
Bowl 1
Bowl 2
tinking_in_java.BlockBow
5.8数组初始化
int [] a;
int a[];都可以
为什么不能写成 int a[3] ? 因为在定义区只是申明了一个变量,作为一个数组的引用,没有给他本身分配任何空间.
数组有3中初始化方式:
int a1[] = {1, 2, 3};
int a2[] = new int[]{1, 2, 3};
int a3[] = new int[3];
// int[] arr=new int[3]{1,2,3} 这是不合语法的,因为 int[3] 的意思是分配3个空间大小,
// 同时把所有的值都赋0,而{1,2,3}又是直接赋值 .这两种意义上冲突了.所以语法规定不能这么同时赋值
float[][][] ratings = new float[9][][];
//只需要能确定ratings 数据的长度就可以
5.9枚举类型
eunm 看起来像一个新的数据类型,其实是一个类.java.lang.Enum
网友评论