天天看點

java enum 初始化_OnJava8_初始化和清理

Java對象初始化通過構造器,清理通過垃圾收集器(Garbage Collector, GC)

構造器

無參構造函器,有參構造器

如果建立一個類,沒有自定義構造器,編譯器會自動建立一個無參構造器

方法重載

函數名相同,參數個數或者參數類型不同,也可參數順序不同(不推薦)

this關鍵字

this可以表示目前對象的引用,不能用于靜态方法(靜态方法與對象無關)

public class Leaf{

int i = 0;

Leaf increment(){

this.i++;

return this;

}

void print(){

System.out.println("i = "+i);

}

public static void main(String [] args){

Leaf x = new Leaf();

x.increment().increment().increment.print();

}

}

this 關鍵字在向其他方法傳遞目前對象時也很有用:

class Person {

public void eat(Apple apple) {

Apple peeled = apple.getPeeled();

System.out.println("Yummy");

}

}

public class Peeler {

static Apple peel(Apple apple) {

// ... remove peel

return apple; // Peeled

}

}

public class Apple {

Apple getPeeled() {

return Peeler.peel(this);

}

}

public class PassingThis {

public static void main(String[] args) {

new Person().eat(new Apple());

}

}

this 在構造器中如果被傳入一個參數清單,則是通過最直接的方式顯示得調用比對參數清單得構造器

public class Flower {

private int preCount = 0;

String s = "initial value";

Flower(int preCount){

this.preCount = preCount;

System.out.println("Constructor w/ int arg only, preCount = " + preCount);

}

Flower(String s){

System.out.println("Constructor w/ string arg only, s = " + s);

this.s = s;

}

Flower(int preCount, String s){

this(preCount);

this.s = s;

System.out.println("String & int args");

}

Flower(){

this(7,"hi");

System.out.println("no-arg constructor");

}

public void print(){

System.out.println("preCount = " + preCount + " s = " + s);

}

public static void main(String []args){

Flower flower1 = new Flower();

flower1.print();

// Tree tree1 = new Tree(1);

// flower1.print();

// flower1.preCount = 2;

// flower1.print();

}

}

class Tree{

private int height;

Tree(int height){

this.height = height;

}

}

成員變量和參數清單中變量同名,用this.s來表明指代得是成員變量,防止混淆

在構造器中調用構造器

在構造器中可以通過this加參數清單的形式調用其他構造器

在一個構造器内隻可以通過this調用一次其他的構造器

必須首先調用構造器

不能在非構造器的方法中調用構造器

static的含義

不能在靜态方法中調用非靜态方法和this,後兩者與對象有關,靜态方法與對象無關

非靜态方法可以調用靜态方法

靜态方法隻能調用靜态變量

垃圾回收器(Garbage Collector)

垃圾回收器一邊回收記憶體,一邊使堆中的對象緊湊排列

引用計數,每個對象有一個引用計數器,每當有引用指向該對象時,引用計數加1,當引用離開作用域或者置null時,引用計數器減1。當引用計數器為0時,釋放其記憶體空間

如果從棧或靜态存儲區出發,周遊所有的引用,你将會發現所有"活"的對象。對于發現的每個引用,必須追蹤它所引用的對象,然後是該對象包含的所有引用,如此反複進行,直到通路完"根源于棧或靜态存儲區的引用"所形成的整個網絡。

Java虛拟機采用一種自适應的垃圾回收技術,停止-複制(stop-and-copy)和标記-清掃(mark-and-sweep)相結合。

"标記-清掃"所依據的思路仍然是從棧和靜态存儲區出發,周遊所有的引用,找出所有存活的對象。但是,每當找到一個存活對象,就給對象設一個标記,并不回收它。隻有當标記過程完成後,清理動作才開始。在清理過程中,沒有标記的對象将被釋放,不會發生任何複制動作。"标記-清掃"後剩下的堆空間是不連續的,垃圾回收器要是希望得到連續空間的話,就需要重新整理剩下的對象

構造器初始化

自動初始化發生在構造器初始化之前

類中變量定義初始化在構造器之前

靜态的基本類型,如果你沒有初始化它,那麼它就會獲得基本類型的标準值,如果是對象引用,就是null。

加載類->如果類是第一次加載則初始化靜态成員變量->初始化非靜态成員變量

導緻類加載的原因: 1、new 一個類的對象,(構造器其實也是靜态方法) ; 2、調用類的靜态方法和靜态成員變量

建立一個類的對象過程:

1、構造器其實也是靜态方法,加載類,Java解釋器在類路徑中查找,定位java.com.util...class;

2、加載類之後,首先初始化靜态成員變量(如果是第一次加載類);

3、當通過new 方法建立對象,在堆上配置設定記憶體空間;

4、配置設定的存儲空間首先會被清零,對象的基本類型資料設定為預設值,引用設定為null;

5、執行所有出現在字段定義處的初始化動作;

6、執行構造器。

靜态塊和其他靜态初始化動作一樣,僅在第一次類加載時執行

隻有new對象的類加載才會初始化非靜态屬性

數組初始化

靜态數組初始化

int [] a = {1,2,3,4,5};

動态數組初始化

int [] a = new int[5];

int [] intA = new int[5];

System.out.println(intA[0]);

System.out.println(Arrays.toString(intA));

System.out.println("*********");

char [] charA = new char[5];

System.out.println(charA[0]);

System.out.println(Arrays.toString(charA));

System.out.println("*********");

Character [] characterA = new Character[5];

System.out.println(characterA[0]);

System.out.println(Arrays.toString(characterA));

System.out.println("*********");

Integer [] IntegerA = new Integer[5];

System.out.println(IntegerA[0]);

System.out.println(Arrays.toString(IntegerA));

結果:

[0, 0, 0, 0, 0]

*********

[ , , , , ]

*********

null

[null, null, null, null, null]

*********

null

[null, null, null, null, null]

可變參數清單

import java.util.Arrays;

public class OverloadingVarargs2 {

static void f(float i, Character... args) {

System.out.println(i);

System.out.println(Arrays.toString(args));

System.out.println("first");

}

static void f(Character... args) {

System.out.println("second");

}

// 修改為下面函數就不會報錯

// static void f(char c, Character... args) {

// System.out.println("second");

// }

public static void main(String[] args) {

// f(1, 'a');

f('a', 'b');

// System.out.println((float) 'r');

}

}

會報錯

Error:(19, 9) java: 對f的引用不明确

OverloadingVarargs2 中的方法 f(float,java.lang.Character...) 和 OverloadingVarargs2 中的方法 f(java.lang.Character...) 都比對

因為char向上轉換(隐式轉換)到float和裝箱為Character優先級相同,如果改為注釋,char能找到對應的參數類型,就不會産生歧義。

枚舉類型 enum

public enum Course {

ENGLISH, CHINESE, MATH, PHYSICAL,

}

public class EnumTest {

Course takeCourse;

EnumTest(Course takeCourse) {

this.takeCourse = takeCourse;

}

public static void main(String[] args) {

Course course1 = Course.CHINESE;

System.out.println(course1);

for (Course c1 : Course.values())

System.out.println(c1.ordinal());

EnumTest test1 = new EnumTest(Course.CHINESE);

EnumTest test2 = new EnumTest(Course.ENGLISH);

EnumTest test3 = new EnumTest(Course.MATH);

test1.printTakeCourse();

test2.printTakeCourse();

test3.printTakeCourse();

}

private void printTakeCourse() {

switch (this.takeCourse) {

case ENGLISH:

System.out.println("take english");

break;

case CHINESE:

System.out.println("take chinese");

break;

default:

System.out.println("take other courses");

break;

}

}

}

enum類型适用于switch;

values() 方法按照 enum 常量的聲明順序,生成這些常量值構成的數組;

ordinal() 方法表示某個特定 enum 常量的聲明順序。