Java學習點滴——初識Java

基於《Java編程思想》第四版java

前言

「程序就是算法加數據結構」,而算法就是控制語句加操做符,編寫一個程序就是使用控制語句加操做符去操做數據結構,所以我從Java的控制語句、操做符以及如何組織數據結構開始入手。由於有C/C++的基礎,因此難免會以對比的方式去理解Java。程序員

控制語句

除了沒有goto,Java的控制流程的關鍵字和C++是同樣的,很好理解。不過Java中的breakcontinue除了C++的正常做用外(跳出或繼續當前循環),還有相似C++中goto的功能,可是使用上是有限制的,即標籤與forwhile(){}do{}while()switch之間不能有其餘語句,不然就會有編譯錯誤。算法

  • 使用break跳轉到標籤後,會直接跳過標籤後緊跟着的循環或者switch代碼,而不是從標籤位置從新開始執行。
int[] a = {1,2,3,4};
Label:
// 這裏不能有任何語句
for( int i : a ){
    System.out.println("loop 1 i = " + i);
    for( int j : a ){
        System.out.println("loop 2 j = " + j);
        break Label; 
    }
}
// break Lable後會直接執行下面的代碼,而不是繼續循環
System.out.println("loop over");
  • 使用continnue跳轉到標籤後,會繼續執行標籤後緊跟着的循環代碼,但並不是重頭開始執行而是從本來的基礎上繼續執行
int[] a = {1,2,3,4};
Label:
// 這裏不能有任何語句
for( int i : a ){
    System.out.println("loop 1 i = " + i);
    for( int j : a ){
        System.out.println("loop 2 j = " + j);
        continue Label; 
    }
}
System.out.println("loop over");

運行以上代碼就會發現break Label的含義就是跳出Label標識的循環,而continue Label的含義是繼續循環Label標識的循環,這和C++的goto是不一樣的。C++中的goto會將讓程序執行流回到Label的位置,從新執行Label後的代碼。編程

操做符

Java多了一個無符號右移操做符>>>,其餘都和C/C++同樣,也很好掌握。不過Java中沒法進行操做符重載,所以理論上操做符應該只能做用於數值類型。但實際上,Java的String類型也可使用=++=操做符,我想應該是由於字符串的賦值和拼接是很常見的操做,因此Java就在內部偷偷給String類型作了這些操做符的重載。這雖然帶來了必定的便利,可是由於String類型的其餘操做符並無重載,因此讓我感受不一致,比較難受。好比下面這段代碼,由於String==並未重載,因此並不會打印"same string"數據結構

String s1 = new String("hello");
String s2 = new String("hello");
if( s1 == s2 ){
    System.out.println(「same string」);
}

在C++中,則能夠經過操做符重載,使得std::string類型可使用==操做符比較是否爲相同字符串,很一致。函數

還有一點,Java中並無sizeof操做符。我想這是由於Java不想讓程序員去關注內存分配,天然也就無需關心類型大小,再者基礎類型的大小在Java中是固定的,因此sizeof就無用武之地了。C中分配內存的函數,如malloc等,都是須要指定大小的,且基礎類型在不一樣平臺的大小多是不同大的,所以必須有sizeof計算大小。oop

類型

Java有如下基礎類型

這些基礎類型的大小都是固定的,並且全部數值類型都是有符號的。學習

Java經過class關鍵字來自定義類型,其結構與C++相似,只是不須要在}後加;指針

class MyType{
     ...
}

C++中的自定義類型除非指定繼承不然是沒有繼承關係的,可是在Java中全部類型都隱式繼承自Object。Java中有不少已經定義好的類型,好比基礎類型的包裝器類型、String等等,學習並使用這些已經定義好的類型是水磨工夫,起初瞭解一下就能夠了。code

Java的函數的定義語法和C++是如出一轍的,可是函數只能在類型的命名空間裏即只能在class {這裏面}定義,而不能在全局命名空間中定義。函數在Java中應該叫方法,不知道叫函數會不會有誤解。
Java的自定義類型中能夠包含其餘類型的變量或者繼續定義類型(內部類)。其餘類型的變量,C++中叫成員變量,但彷佛Java中叫域。

實例化類型

Java實例化類型的語法和C++如出一轍,可是有一些限制。

  • 基礎類型只能直接實例化,沒法用new實例化
int x = 1;
  • 特定類型,好比基礎類型的包裝器類型、String類型等,能夠直接賦值(本質上是編譯器幫你作了一次隱式轉換),或使用new實例化
Integer n1 = 1;
Integer n2 = new Integer(1);
String s1 = "hello";
String s2 = new String("hello"); // 不推薦這麼用,轉換後的字節碼更多
  • 其他類型的實例化必須使用new關鍵字
MyType m = new MyType(1);
// MyType m = 1; 不會進行一次隱式轉換,編譯報錯

能夠感受到很強烈的不一致!!

基礎類型的變量空間存儲的是真實數值,而其餘類型的變量空間存儲的是實例化對象的引用。Java中的引用和C++的引用並非一個意思,Java中的引用更像是C++中的指針。在C++中,引用是一個實例對象的別名,一旦肯定就沒法變動其引用的對象,可是在Java中能夠變動引用的實例化對象,好比

Integer a = new Integer (1);
a = new Integer(2);

在函數傳參中,這點就更明顯了,好比下面的函數,咱們叫ab是引用,但實際呢,這只是值傳遞swap()中的交換並不會影響實際對象的值。整個函數就是交換了一下ab這兩個局部變量指向的對象而已。

void swap(Integer a, Integer b){
    Integer tmp = a;
    a = b;
    b = tmp;
}

就相似於如下C++代碼

void swap(int* a, int* b){
    int* tmp = a;
    a = b;
    b = tmp;
}

從上面看所謂對象的引用其實就是把對象的地址值(不是內存地址,只須要是一個惟一位置的標識便可)保存到了變量空間裏。從這個角度去理解,基礎類型的變量和其餘類型的變量存儲的東西能夠認爲是同樣的。Java中只有值傳遞

訪問控制

和C++同樣,Java也有針對類、方法、域的訪問權限控制。Java除了publicprotecetedprivate這些權限外,還有一種包訪問權限。當不帶另外三個權限關鍵字時,就是包訪問權限了。在Java中能夠將一些源文件定義爲一個包,所以就有了包訪問權限,即同一包內能夠訪問。Java中的包相似於C++的動態庫,C++中雖然沒有明確說包(庫)訪問權限,但其實是有的,好比Linux下能夠經過連接時的參數version-script指定動態庫的導出符號,那些未導出的符號就是包(庫)訪問權限了。

文件組織

一個.java源文件中只能有一個public類,且源文件名必須和這個public類的名字保持一致。其餘類只能是包訪問權限,固然內部類是不受這個限制的,能夠是任意權限。每一個類型均可以有一個public static void main(String[] agrs),這是執行的入口。由於函數都是在類的命名空間裏,因此存在多個main()也是能夠的,指定執行的類就會調用對應的main()

結語

由於IDE的強大,因此不少東西只須要腦子裏有點印象,作到寫代碼時看到錯誤提示就能想到是爲何就能夠了,熟能生巧。

相關文章
相關標籤/搜索