程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> java基礎知識學習筆記(二)

java基礎知識學習筆記(二)

編輯:JAVA綜合教程

java基礎知識學習筆記(二)


java基本的程序設計結構

1 一個簡單的java例子

public class FirstExample{
    public static void main(String[] args){
        System.out.println("we will not use 'hello world' ");
    }
}

從這個程序中,我們可以知道哪些?
1 java對大小寫很敏感,main寫成Main,程序無法執行
2 public訪問修飾符,控制程序的其他部分對這段代碼的訪問級別
3 class表名java程序包含在類中,這裡,只需要將類作為一個加載程序邏
輯的容器,程序邏輯定義了應用程序的行為。
4 class後面跟的是類名,命名規則:類名是以大寫字母開頭的名詞。如果
名字由多個單詞組成,每個單詞的第一個字母都應該大寫。其他等同於標
識符的命名規則。
5 文件名與公有類的類名一致,如FirstExample.java
6 每個java應用程序必須有一個main方法
7 {}方法體開始和結束。每個句子必須用‘;’結束,回車不是結束的標志,因此,可以將一條java語句寫在多行上
8 System.out.println(),方法調用
9 “”引用字符串
10 方法可以沒有參數,也可以有多個參數,但必須用()表示例如,不帶
參數的println方法只打印一個空行。使用下面的語句:

System.out.println()
Note:
運行編譯程序時, Java虛擬機將從指定類中的main方法開始執行(這裡的“方法”就是Java中所說的“函數”),
因此為了代碼能夠執行,在類的源文件中必須包含一個main方法。當然,也可以將用戶自定義的方法添加到類中,
並且在main方法中調用它們。

根據Java語言規范, main方法必須聲明為public

Java的類與C++的類很相似,但還是有些差異會使人感到困惑。
例如, Java中的所有函數都屬於某個類的方法(標准術語將其稱為方法,而不是成員函數)。
因此, Java中的main方法必須有一個外殼類。讀者有可能對C++中的靜態成員函數( static member functions)十分熟悉。
這些成員函數定義在類的內部,並且不對對象進行操作。 Java中的main方法必須是靜態的。
最後,C/C++一樣,關鍵字void表示這個方法沒有返回值,所不同的是main方法沒有給操作系統返回“退出代碼”。
如果main方法正常退出,那麼Java應用程序的退出代碼為0,表示成功地運行了程序。
如果希望在終止程序時返回其他的代碼,那就需要調用System.exit方法。

2 注釋

與多數設計語言一樣,java中的注釋不會出現在可執行程序中。
注釋類型:
單行://注釋的內容
多行:/*注釋的內容 */
另一種:/**注釋的內容*/

Note:
在Java中, /* */注釋不能嵌套。也就是說,如果代碼本身包含了一個*/,就不能用/*和*/將注釋括起來。

3 數據類型

四種整型,兩種浮點,一種char,一種Boolean
1 整型

類型 存儲要求 取值范圍 int 4字節 -2 147 483 648~2 147 483 647(正好超過20億) short 2字節 -32 768~32 767 long 8字節 -9 223 372 036 854 775 808~9 223 372 036 854 775 807 byte 1字節 -128~127
在java中,整型的取值范圍固定,與平台無關,這就解決了移植性的問題,而c/c++需要針對不同的處理器選擇最為有效的整型,會導致整數溢出問題

2 浮點型

類型 存儲要求 取值范圍 float 4字節 大約±3.402 823 47E+38F(有效位數為6~7位) double 8字節 大約±1.797 693 134 862 315 70E+308(有效位數為15位)
常量Double.POSITIVE_INFINITY、 Double.NEGATIVE_INFINITY和Double.NaN(與相應的Float類型的常量一樣),例如:
一個正整數除以0的結果為正無窮大。計算0/0或者負數的平方根結果為NaN。

檢測一個數是不是NaN,不能
if(x==Double.NaN)
//所有"非數值"的值都認為是不相同的。可以用Double.NaN(x)
if(Double.NaN(x))

3 char類型
記住以下幾點:
1 ‘A’和“A”不同:前者是字符常量65,後者是包含字符A的字符串
2 在”和”“中可以假如轉義字符,但只有\u可以不在內部,如\u005B和\u005D是(和)的編碼。
3 java中采用的UTF-16描述一個代碼單元
4 強烈建議不要在程序中使用char類型

4 boolean型

在C++中,數值或指針可以代替boolean值。整數0相當於布爾值false,非0值相當於布爾值true。在Java中則不行。
因此, Java應用程序員不會遇到下述麻煩:
if(x=0)//
在C++中這個測試可以編譯運行,其結果總是false。而在Java中,這個測試將不
能通過編譯,其原因是整數表達式x = 0不能轉換為布爾值。

4 變量

記住一下幾點:
1 變量名區分大小寫
2 在c/c++,區分變量定義和聲明,如:
int i=10;//定義變量
extern int i;//聲明一個變量
java中不做區分,可以直接寫成:int i=10;//聲明,定義,初始化

3 與變量對應的就是常量,用final聲明,通常常量名使用大寫,常量不能更改,如:
final int PI=3.14;

4 希望某個常量可以在一個類中的多個方法中使用,通常將這些常量稱為類
常量。可以使用關鍵字static final設置一個類常量。需要注意,類常量的定義位於main方法的外部。

 const是Java保留的關鍵字,但目前並沒有使用。在Java中,必須使用final定義常量。

5 運算符

關於運算符需要注意的一些問題:
1 整數除0會產生一個異常,浮點數除0則會得到無窮或NaN
2 自增運算符與自減運算符,舉個例子:

int m=7;
int n=7;
int a=2*++m;//m=8,a=16
int b=2*n++;//n=8,b=14

3 關系運算符與boolean運算符,舉個例子:

if(x!=0&&1/x>x+y)
當x為0時,不會計算第二部分。因此,若x為0, 1/x不被計算,也不會出現除以0的錯誤。&&和 || 是按照“短路”方式求值的。

4 位運算符(這個用的較少,但容易忽略)

&( "與")、 |( "或")、 ^( "異或")、 ~( "非")
“ >>”和“ <<”運算符將二進制位進行右移或左移操作
>>>運算符將用0填充高位; >>運算符用符號位填充高位。沒有<<<運算符

對移位運算符右側的參數需要進行模32的運算(除非左邊的操作數是long類型,在這種情況下需對右側操作數模64)。例如, 1 << 35與1 << 3或8是相同的。

5 數學函數和常量
舉個例子:

double x=4;
double y=Math.sqrt(x);
System.out.println(y);//print 2.0
Note:
println方法和sqrt方法存在微小的差異。 println方法操作一個定義在System類中的System.out對象。但是, Math類中的sqrt方法操作的不是對象,這樣的方法被稱為靜態方法。

提示:從JDK 5.0開始,不必在數學方法名和常量名前添加前綴“ Math.”,而只要在源文件的頂部加上下列內容就可以了。
例如:
import static java.lang.Math.*;

6 數值之間的轉換規則
貼個圖,不解釋
這裡寫圖片描述
實心箭頭,表示無信息丟失的轉換;虛箭頭,表示可能有精度損失的轉換。
例如:123 456 789是一個大整數,它所包含的位數比float類型所能夠表達的位數多。當將這個整型數值轉換為float類型時,將會得到同樣大小的結果,但卻失去了一定的精度。
int n=123456789;
float f=n;//f is 1.234567892 E8

當使用數值進行二元運算時,先將兩個操作數轉換為同一類型,轉換規則如下:
如果兩個操作數中有一個是double類型的,另一個操作數就會轉換為double類型。
否則,如果其中一個操作數是float類型,另一個操作數將會轉換為float類型。
否則,如果其中一個操作數是long類型,另一個操作數將會轉換為long類型。
否則,兩個操作數都將被轉換為int類型。

強制轉換,舉個例子;

double x=9.997;
int n=(int)x;//n is 9

如果取最接近的整數,可以使用:

double x=9.997;
int n=(int)Math.round(x);//n is 10

不要在boolean類型與任何數值類型之間進行強制類型轉換,如果轉換可以使用條件表達式b? 1:0。

7 括號與運算符級別
如果不使用圓括號,就按照給出的運算符優先級次序進行計算。同一個級別的運算符按照從左到右的次序進行計算(除了表中給出的右結合運算符外。)

運算符 結合性 [ ] . ( ) (方法調用) 從左向右 ! ~ ++ – + (一元運算) - (一元運算) ( ) (強制類型轉換) new 從右向左 */ % 從左向右 加 - 從左向右 << >> >>> 從左向右 < <= > >= instanceof 從左向右 == != 從左向右 & 從左向右 ^ 從左向右 按位或 從左向右 && 從左向右 或 從左向右 ?: 從右向左 = += -= *= /= %= &= 或= ^= <<= >>= >>>= 從右向左

8 枚舉類型
這裡先不做解釋

6 字符串

從概念上講,java字符串就是Unicode字符序列。如,串“ Java\u2122”由5個Unicode字符J、 a、 v、 a和TM。java沒有內置的字符串類型(基本數據來了類型裡沒有),在java標准類庫裡提供了一個預定義的String類。每個“”括起來的都是字符串的一個實例:

String string="";//an empty string
String String="hello";//String是Java的一個類,類名是標識符,所以String可以做標識符。
String sizeof="sizeof";//There is no sizeof operator.Java中沒有sizeof運算符,所以sizeof可以作為標識符

1 子串
舉個例子:

String greeting="hello";
String s=greeting.subString(0,3);//s is hel

解釋一下subString函數:
第一個參數,從0位置開始;第二個參數,到3結束(0,1,2,不包括3)。
則求子串的長度就比較簡單,即3-0=3。
2 拼接
所謂拼接,即用+連接兩個字符串。舉個例子:

String a="hello";
String b="world";
int age=13;
String c=a+b;//c is helloworld
String d=a+age;//d is hello13

兩個原則:
1 單詞之間沒有空格, +號按照給定的次序將兩個字符串拼接起來
2 當將一個字符串與一個非字符串的值進行拼接時,後者被轉換成字符串

3 不可變字符串
String類沒有提供修改字符串的方法,如果希望將greeting的內容修改為“ Help!”,不能直接地將greeting的最後兩個位置的字符修改為‘ p’和‘ !’。在c中實現起來,就比較麻煩:

在這裡寫提一下,將字符串認為是字符型數組:
char greeting[]="hello";
這種認識是錯誤的, Java字符串更加像char*指針,
char *greeting="hello";
當采用另一個字符串替換greeting的時候, c代碼主要進行下列操作:
char *temp=malloc(6);
strncpy(temp,greeting,3);
strncpy(temp+3,"p!",3);
greeting=temp;

在Java中實現這項操作非常容易。首先提取需要的字符,然後再拼接上替換的字符串:

greeting=greeting.subString(0,3)+"p!";//greeting is help!

在java的源碼文檔中,將String類對象成為不可變字符串,在這裡會有一個疑問:

String greeting="hello";
greeting="help!";

以上代碼只是修改了greeting引用的地址,即原來引用的是“hello”,後來引用“help!”,那原來的“hello”去哪了?

這樣做會不會產生內存遺漏呢?畢竟,原始字符串放置在堆中。十分幸運, Java將自動地進行垃圾回收。如果一塊內存不再使用了,系統最終會將其回收。

當然,C++ string對象也自動地進行內存的分配與回收。內存管理是通過構造器、賦值操作和析構器顯式執行的。然而, C++字符串是可修改的,也就是說,可以修改字符串中的單個字符。

為什麼這麼設計?看起來好像修改一個代碼單元要比創建一個新字符串更加簡潔,效率更高?

答案是:也對,也不對。的確,通過拼接“ Hel”和“ p!”來創建一個新字符串的效率確實不高。但是,不可變字符串卻有一個優點:編譯器可以讓字符串共享。

為了弄清具體的工作方式,可以想像將各種字符串存放在公共的存儲池中。字符串變量指向存儲池中相應的位置。如果復制一個字符串變量,原始字符串與復制的字符串共享相同的字符。

總而言之, Java的設計者認為共享帶來的高效率遠遠勝過於提取、拼接字符串所帶來的低效率。查看一下程序會發現:很少需要修改字符串,而是往往需要對字符串進行比較。

4 檢查字符串是否相等
如果你認為比較是否相等,可以用“==”即可,那你就錯了,舉個例子:

String greeting="hello";//initialize greeting to a string
if(greeting="hello")...
//probably true
if(greeting.subString(0,3)=="hel")...
//probably false
why?

如果虛擬機始終將相同的字符串共享,就可以使用 == 運算符檢測是否相等。但實際上只有字符串常量是共享的,而+或substring等操作產生的結果並不是共享的。因此,千萬不要使用 == 運算符測試字符串的相等性,以免在程序中出現糟糕的bug。從表面上看,這種bug很像隨機產生的間歇性錯誤。

那在java中怎麼比較字符串是否相等?

String greeting=hello;
"hello".equals(greeting)...//true
"Hello".equalsIgnore(greeting)...//true,不區分大小寫,
Note:
對於習慣使用C++的string類的人來說,在進行相等性檢測的時候一定要特別
小心。 
C++的string類重載了==運算符以便檢測字符串內容的相等性。可惜Java沒有采用這種方式,
它的字符串“看起來、感覺起來”與數值一樣,但進行相等性測試時,其操作方式又類似於指針。
語言的設計者本應該像對+那樣也進行特殊處理,即重定義 == 運算符。
當然,每一種語言都會存在一些不太一致的地方。C程序員從不使用 == 對字符串進行比較,而使用strcmp函數。 
Java的compareTo方法與strcmp完全類似,因此,可以這樣使用:
if(greeting.comepareTo("hello")==0)...
不過,使用equals看起來更為清晰。

5 代碼點與代碼單元
什麼是代碼點和代碼單元?
Java中,char[]、String、StringBuilder和StringBuffer類中采用了UTF-16編碼,使用U+0000~U+FFFF來表示一個基本字符(BMP字符),但是位於U+D800到U+DBFF和U+DC00到U+DFFF的char被視為無定義字符。大多數的常用Unicode字符使用一個代碼單元就可以表示,而輔助字符需要一對代碼單元表示。即:基本字符用一個char表示,輔助字符使用一對char表示。

Java使用代碼點(Unicode code pointer)這個概念來表示范圍在U+0000與U+10FFFF之間的字符值(int型),代碼單元(Unicode code unit)表示作為UTF-16編碼的代碼單元的 16位char值(char型)。也就是說,可能存在一個字符,它的代碼點數量是1,而代碼單元數量是2。所以,代碼單元的數量並不一定是字符的數量。

相比之下,代碼單元更加偏底層。

相關函數:
length()函數返回采用UTF-16編碼標識的給定字符串所需要的代碼單元的數量。
codePointCount()函數返回采用UTF-16編碼標識的給定字符串所需要的代碼點的數量。

測試程序:


package com.xujin;

public class Test{
    public static void main(String...args){     
        char[] ch = Character.toChars(0x10400);
        System.out.printf("U+10400 高代理字符: %04x\n", (int)ch[0]);//d801
        System.out.printf("U+10400 低代理字符: %04x\n", (int)ch[1]);//dc00   
        String str = new String(ch);
        System.out.println("代碼單元長度: " + str.length());//2
        System.out.println("代碼點數量: " + str.codePointCount(0, str.length()));//1
        System.out.println(str.codePointAt(0));//返回給定位置開始或結束的代碼點,66560
        System.out.println(str.charAt(1));//返回給定位置的代碼單元,由於未定義,返回?

        //遍歷一個字符串,打印出所有字符的代碼點
        str += "Hello,world!";
        int i = 0;
        int cp = str.codePointAt(i);
        while(i < str.length()){
            System.out.println(str.codePointAt(i));
            if(Character.isSupplementaryCodePoint(cp))
                i += 2;//如果cp所在的位置是代碼點的第一部分,執行此處
            else i++;
        }
        /*
         * 66560 
         * 72 
         * 108 
         * 111 
         * 119 
         * 114 
         * 100
         */
    }
}

java字符串是由char序列組成,char是一個采用UTF-16編碼表示
Unicode代碼點的代碼單元。常用Unicode字符使用一個代碼單元就可以表示,而輔助字符需要一對代碼單元表示。

length方法將返回采用UTF-16編碼表示的給定字符串所需要的代碼單元數量。例如:

String greeting="hello";
int l=greeting.length();//5

要想得到實際的長度,即代碼點數量,可以調用:

int cpCount = greeting.codePointCount(0, greeting.length() );
//為什麼說這個是實際長度?

調用s.charAt(n) 將返回位置n的代碼單元, n介於0~s.length()-1之間。例如:

char first=greeting.charAt(0);//first is h
char last=greeting.charAt(4);//last is o
//返回字符

//要想得到第 i 個代碼點,應該使用下列語句
int index = greeting.offsetByCodePoints(0, i);
int cp = greeting.codePointAt(index);
//返回ascii值

6 字符串API

7 輸入輸出

8 控制流程

9 大數值

10 數組

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved