概述和目標
學習如何編程解決實際問題。通過這些問題,學到如何利用基本數據類型、變量、常量、操作符、表達式以及輸入/輸出來進行基本的程序設計。
一、創建、編譯和執行java程序
我們從一個簡單的Java程序開始,該程序在控制台上顯示“Welcome to Java!".
public class Welcome{ public static void main(String[] args){ //在控制台顯示Welcome to Java! System.out.println("Welcome to Java!"); } }
第一行定義了一個類。每個java程序至少應該有一個類。每個類都有一個名字。按照慣例,類名都是以大寫字母開頭的。本例中,類名為Welcome。
第二行定義主方法(main method)。程序是從main方法開始執行的。一個類可以包含多個方法。main方法是程序開始執行的入口。
方法是包含語句的結構體。本程序中的main方法包括了System.out.println 語句。該語句在控制台顯示Welcome to Java!。字符串是一個編程術語,表示一個字符序列。一個字符串必須放入雙引號中。java中的每條語句都以分號(;)結束,也稱為語句結束符。
關鍵字(keyword)或保留字(reserved word)對編譯器而言都是有特定含義的,所以不能在程序中用作標識符。
第三行是注釋(comment),它對程序進行解釋說明。注釋幫助程序員進行相互溝通以及理解程序。注釋不是程序設計語句,所以編譯器編譯程序時是忽略注釋的。在java中,在單行上用兩個斜杠(//)引導注釋,稱為單行注釋;在一行或者多行用/*和*/括住注釋,稱為多行注釋;在一行或者多行用/**和*/括住注釋,稱為文檔注釋,文檔注釋允許你在程序(一般用於類,接口等類型上以及方法上)中嵌入關於程序的信息。你可以使用 javadoc 工具軟件來生成信息,並輸出到HTML文件中。
程序中的一對花括號將程序的一些組成部分組合起來,形成一個塊(block)。每個塊以左花括號{開始以右花括號}結束。每個類都有一個將該類的數據和方法放在一起的類塊。每個方法都有一個將該方法的語句放在一起的方法塊。塊是可以嵌套的。
這個程序會顯示一條信息,很容易將該程序擴展為顯示更多的信息:
public class WelcomeWithThreeMessage{ public static void main(String[] args){ //在控制台顯示Welcome to Java! System.out.println("Welcome to Java!"); System.out.println("哇哦,Java好有趣!"); System.out.println("我要學Java!"); } }
更進一步,你可以進行數學計算,並將結果顯示到控制台上。
public class ComputeExpression{ public static void main(String[] args){ System.out.println((10.5 + 2 * 3) / (45 - 3.5)); } }
java中的乘法操作符是*,除法操作符是/,將一個數學表達式翻譯成java表達式是一個非常直觀的過程,在后面的章節進一步討論java表達式。
在程序執行之前,必須創建程序並進行編譯。這個過程是反復執行的。如果程序有編譯錯誤,必須修改程序來糾正錯誤,然后重新編譯。如果程序有運行時錯誤或者不能產生正確的結果,必須修改這個程序,重新編譯它,然后重新執行。
注意:源文件的擴展名必須是.java,而且文件名必須與公共類名完全相同。例如我們的第一個程序源文件必須命名為Welcome.java,因為公共的類名就是Welcome。可以使用任何一個文本編輯器或者集成開發環境來創建和編譯java源文件。
java編譯器將java源文件翻譯成java字節碼文件。下面的命令就是用來編譯Welcome.java的:
javac Welcome.java
如果沒有出現語法錯誤,編譯器(compiler)就會產生一個擴展名為.class的字節碼文件。java語言是高級語言,而java字節碼是低級語言。字節碼類似於機器指令,但它是體系結構中立的,是可以在任何帶Java虛擬機(JVM)的平台上運行的。虛擬機不是物理機器,而是一個解釋java字節碼的程序。這正是java的優點之一:java字節碼可以在不同的硬件平台和操作系統上運行(一次編譯,到處運行)。java源代碼編譯成java字節碼,然后java字節碼被JVM解釋執行。你的java代碼可能要用到java庫中的代碼。JVM將執行你的程序代碼以及庫中的代碼:
執行java程序就是運行程序的字節碼,可以在任何一個裝有JVM的平台上運行字節碼(跨平台),解釋java字節碼。解釋的過程就是一次將字節碼中單獨的一步翻譯為目標機器語言代碼,翻譯完后就立即執行這一步。下面的命名用來運行第一個程序字節碼
java Welcome
注意:在執行Java程序時,JVM首先使用一個名為類加載器(class loader)的程序將類的字節碼加載到內存中。如果您的程序使用其他類,類加載器會在需要它們之前動態加載它們。加載類之后,JVM使用一個名為字節碼驗證器(bytecode verifier)的程序來檢查字節碼的有效性,並確保字節碼不違反Java的安全限制。Java強制執行嚴格的安全性,以確保來自網絡的Java程序篡改和損害您的計算機。
二、程序設計風格和文檔
程序設計風格決定程序的外觀,文檔是關於程序的解釋性評注和注釋的一個結構體。良好的程序設計風格和適當的文檔可以減少出錯的機率,並且提高程序的可讀性。
1.正確的注釋和注釋風格
2.正確的縮進和空白
3.塊的風格
三、編寫簡單的程序
編寫簡單的程序涉及如何設計解決問題的策略,以及如何應用編程語言實現這個策略。
首先,我們來看一個計算圓面積的簡單問題。該如何編寫程序解決這個問題呢?編寫程序涉及如何設計算法以及如何將算法翻譯成程序指令,即代碼。算法描述的是:如果要解決問題,所需要執行的動作以及這些動作執行的順序。算法可以幫助程序員在使用程序設計語言之前做一個規划。算法可以用自然語言或者偽代碼(自然語言和程序設計語言混在一起使用)描述。這個程序的算法描述如下:
1.讀入半徑
2.利用公式計算面積:面積 = 半徑 x 半徑 x π
3.顯示面積
編碼將一個算法翻譯稱程序。我們已經知道每個java程序都是一個類的聲明開始,在聲明類名緊跟在class后面。假設選擇ComputeArea作為這個類的類名。這個程序的框架就如下所示:
public class ComputeArea{ }
每一個java應用程序都有一個main方法,程序從該方法開始執行:
public class ComputeArea{ public static void main(Stirng[] args){ //第一步:讀入半徑 //第二步:計算面積 //第三步:顯示面積 } }
這個程序需要讀取用戶從鍵盤輸入的半徑。這就產生兩個重要問題:
- 讀取半徑
- 將半徑存儲在程序中
先來解決第二個問題。為了存儲半徑,在程序中需要聲明一個稱作變量的符號。變量代表了存儲在計算機內存中的一個值。變量名應該盡量選擇描述性的名字,在這個例子中用radius表示半徑、用area表示面積而不是用x和y這樣的名字。為了讓編譯器知道radius和area是什么,需要指明它們的數據類型。這稱為聲明變量。java提供簡單數據類型來表示整數、實數、字符以及布爾類型。這些稱為基本數據類型。
實數(帶小數點的數字)在計算機中使用一種浮點的方法來表示。因此我們把實數稱為浮點數。java中,可以使用關鍵字double來聲明一個雙精度的浮點變量。將radius和area聲明為double:
public class ComputeArea{ public static void main(Stirng[] args){
//每個變量都有名字,類型、大小和值 double radius; double area; //第一步:讀入半徑 //第二步:計算面積 //第三步:顯示面積 } }
四、從控制台讀取輸入
可以使用Scanner類從控制台輸入:
Scanner input = new Scanner(System.in); //調用nextDouble()方法來讀取一個double值 double radius = input.nextDouble();
重寫上面程序,提示用戶輸入一個半徑
import java.util.Scanner;//Scanner在java.util包中,使用需要將其導入進來 public class ComputeArea{ public static void main(Stirng[] args){ System.out.println("請輸入圓的半徑"); Scanner input = new Scanner(System.in); //每個變量都有名字,類型、大小和值 double radius = input.nextDouble(); //計算面積 double area = radius * radius * 3.14; //顯示面積 System.out.println("半徑為:" + radius + "的圓的面積為:" + area); } }
Scanner在java.util包中。在第一行被導入。import語句有兩種類型:明確導入和通配符導入。
明確導入時在import語句中指定單個的類:import java.util.Scanner;
通配符導入指使用星號作為通配符,導入一個包中的所有類import java.util.*;
除非要在程序中使用某個類,否則關於被導入包中的這些類的信息在編譯時或運行時是不被導入的。導入語句至少告訴編譯器在什么地方能找到這些類。明確導入和通配符導入在性能上是沒有什么差別的。‘
練習:從鍵盤讀取三個數值,然后顯示它們的平均值。
五、標識符
Java中的包、類、方法、參數和變量的名字。所有的標識符必須遵循以下規則:
- 可由任意順序的大小寫字母、數字、下划線(_)和美元符號($)組成
- 不能以數字開頭
- 不能是關鍵字
合法的標識符
username
user_name
_userName
$username
不合法的標識符
class
3.14
六、變量
變量的概念:
- 內存中的一個存儲區域
- 該區域有自己的名稱(變量名)和類型(數據類型)
- 該區域的數據可以在同一類型范圍內不斷變化
變量用於表示特定類型的數據。為了使用變量,可以通過告訴編譯器變量的名字極其可以存儲的數據類型來聲明該變量。變量聲明告知編譯器根據數據類型為變量分配合適的內存空間。聲明變量的語法如下:
datatype variableName;
示例:
int count;
double radius;
double area;
如果幾個變量為同一類型,允許一起聲明它們:
datatype variable1,variable2,...,variablen;
變量之間用,分開。例如:
int i,jk;
變量通常都有初始值。可以進一步完成變量的聲明和初始化:
int count = 1;
它等同於下面兩條語句:
int count;
count = 1;
也可以使用簡捷的方式來同時聲明和初始化同一類型的變量:
int i = 1, j = 2;
Tips:在賦值給變量之前,必須聲明變量。方法中聲明的變量在使用之前必須被賦值(初始化)。任何時候,都要盡可能一步完成變量的聲明和初始化。這會使得程序易讀同時避免程序設計錯誤。
每個變量都有使用范圍。變量的使用范圍(作用域)是指變量可以被引用到的程序的部分。
七、賦值語句和賦值表達式
賦值語句將一個值指定給一個變量。在java中賦值語句可以作為一個表達式。將等號(=)作為賦值操作符。語法如下所示:
variable = expression;
表達式(expression)表示涉及值、變量和操作符的一個運算,它們組合在一起計算出一個新值:
int i = 1;
double radius = 1.0;
int ret = 5 * (3 / 2);
ret = i + 1;
double area = radius * radius * 3.14;//變量可用在表達式中,也可用於=操作符的兩邊
八、命名常量
一個變量的值在程序執行過程中可能會發生變化,但是常量則表示從不改變的永久數據。在前面的程序中,π是一個常量。如果頻繁使用它但又不想重復地輸入3.14,代替的方式就是聲明一個常量π。語法如下:
final datatype CONSTANTNAME = value;
常量必須在同一條語句中聲明和賦值。單詞final是聲明常量的java關鍵字。
package edu.cduestc.charpter1; import java.util.Scanner; public class ComputeAreaWithConstant { public static void main(String[] args) { final double PI = 3.14; System.out.println("請輸入圓的半徑:"); Scanner input = new Scanner(System.in); //讀取半徑 double radius = input.nextDouble(); //計算圓的面積 double area = PI * radius * radius; //顯示面積 System.out.println("半徑為:" + radius + "的圓的面積為:" + area); } }
使用常量的好處:
1.不必重復輸入同一個值
2.如需修改常量值,只需要在源代碼中的一個地方做修改
3.給常量一個描述性名字會提高程序的易讀性
九、命名習慣
嚴格遵循java的命名習慣可以讓你的程序易於理解,以及避免錯誤。應該確保程序中為標識符(變量、常量、類、方法和參數)所選擇的描述性名字是直觀易懂的。命名是區分大小寫的。
- 使用小寫駝峰命名規則命名變量和方法及參數。例如,變量radius和area以及方法print
- 類名中每個單詞首字母大寫,例如,類名ComputeArea和System。
- 大寫常量中的所有字母,多個單詞用下划線連接,例如,常量PI和MAX_VALUE。
十、數值數據類型和操作
1、整型
為什么會有不同大小的類型,舉個例子比如存 5 這個數據怎么存的?
- byte(8位,-2^8--2^8-1范圍是-128到127)
- short(16位,
-32768
—32767
) - int(32位,
-2147483648
—2147483647
) - long (64位,-
9223372036854775808
—9223372036854775807
)
注意:給long賦值時,因為整數默認是int類型,要轉換為long類型的值,后面加上l或L
上面的byte short int long 最大長度可以通過jdk文檔去找到 具體的范圍。
- 同一個整數可以使用不同的進制表示:
默認的進制10進制
二進制: 是 0b 或者 0B開頭
八進制: 是0開頭
十六進制: 0X (0x) 開頭
上面輸出的是 10進制
為了提高可讀性,Java7 開始 支持數字之間用 _ 分割
2、浮點型(小數型)
A. float(單精度32位) 直接賦值時必須在數字后加上f 或F
B. double( 雙精度64位)
區別:
對於單精度浮點數,運行速度相比double更快,占內存更小,但是當數值非常大或者非常小的時候會變得不精確。雙精度比單精度表示的位數大 精確的位數多,簡單地說, float表示的小數點位數少。
默認浮點數的類型是 double
表現形式:
- 常規 3.14
- 科學計數法(例如 3.14e2 3.14e-2)
注意:
表示float 類型 必須加上f 或者F
float double 不能精確表示一個小數,例如 1.3*1.4
例如 double num= 1.0, 是一個無限接近1.0的一個值
那怎么更精確的表示浮點數呢?BigDecimal
結論:浮點運算很少是精確的,只要是超過精度能表示的范圍就會產生誤差。往往產生誤差不是 因為數的大小,而是因為數的精度。因此,產生的結果接近但不等於想要的結果。尤其在使用 float 和 double 作精確運 算的時候要特別小心。
3、從鍵盤讀取值
4、數值操作符
算術運算符注意問題:
- “+”除字符串相加功能外,還能把非字符串轉換成字符串 ,如: “x”+123;的結果是“x123” 。
- 如果對負數取模,可以把模數負號忽略不記,如:5%-2=1。但被模數是負數就另當別論。
- 對於除號“/”,它的整數除和小數除是有區別的:整數之間做除法時,只保留整數部分而舍棄小數部分。 例如:
int x=3510;x=x/1000*1000;
實際運行結果是多少 ,想想為什么?
操作符%通常用在正整數上,實際上它也可以用於負數和浮點值。只有當被除數是負數時余數才是負的。
示例:計算以秒為單位的時間量所包含的分鍾數和余下的秒數。
package edu.cduestc.charpter1; import java.util.Scanner; public class DisplayTime { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("請輸入一個整數來代表秒數:"); int seconds = input.nextInt(); int minutes = seconds / 60; int remainingSeconds = seconds % 60; System.out.println(seconds + "秒包含" + minutes + "分鍾" + remainingSeconds + "秒"); } }
示例學習:顯示當前時間數,可以通過System.currentTimeMills()返回當前時間的毫秒數。
package edu.cduestc.charpter1; /** * 顯示當前時間數 * @author Adan * */ public class ShowCurrentTime { public static void main(String[] args) { //1.獲取當前時間(總毫秒數) long totalMilliseconds = System.currentTimeMillis();//返回1970年1月1日午夜到現在流逝的毫秒數(1000毫秒 = 1秒) System.out.println(totalMilliseconds); //2.將總毫秒數換算成總秒數 long totalSeconds = totalMilliseconds / 1000; //3.得到當前的秒數 long seconds = totalSeconds % 60; //4.通過總秒數/60得到總分鍾數 long totalMinutes = totalSeconds / 60; //5.通過totalMinutes % 60得到當前分鍾數 long minutes = totalMinutes % 60; //6.通過totalMinutes / 60得到總小時數 long totalHours = totalMinutes / 60 + 8;//位於東八區 //用總的小時數 % 24 得到當前的小時 long hours = totalHours % 24; System.out.println(hours + ":" + minutes + ":" + seconds); } }
十一、增強賦值操作符
經常會出現變量的當前值被使用、修改,然后再重新賦值給該變量的情況。例如,下面的語句將變量count加1.
count = count + 1;
可以使用增強賦值操作符來結合賦值和加法操作符的功能。例如,上面的語句可以寫成:
count += 1;
十二、自增和自減操作符
++:讓變量的值自增1
1)前++:++在變量的前面,先自增1,后運算
2)后++:++在變量的后面,先運算,再自增1
--:讓變量的值自減1
1)前--:--在變量的前面,先自減1,再運算
2)后--:--在變量的后面,先運算,再自減1
十三、數值類型轉換
發生的場景:不同類型的變量之間進行運算
數據類型的轉換分為兩種:
1)自動類型轉換:byte short char ==>int==>long==>float==>double
注意:a.當byte short char 之間進行運算時結果屬於int型;
b.boolean類型不可以轉換為其它的數據類型。
2)強制類型轉換:將容量大的數據類型強制轉換成容量小的數據類型,必須使用"(目標數據類型)"符號;
格式是:小的數據類型 = (小的數據類型)大的數據類型。
注意:強轉后會造成精度的損失(丟失),丟的是高位。.
3)變量與字符串進行運算:
"+":表示的是連接符,即運算結果是字符串
十四、軟件開發過程
軟件開發生命周期是一個多階段的過程,包括需求規范、分析、設計、實現、測試、部署和維護。
開發一個軟件產品是一個工程過程。軟件產品無論多大或者多小,具有同樣的生命周期:需求規范、分析、設計、實現、測試、部署和維護
需求規范是一個規范化的過程,旨在理解軟件要處理的問題,以及將軟件系統需要做的詳細記錄到文檔中。這個階段涉及用戶和開發者之間緊密的接觸。
系統分析旨在分析數據流,並且確定系統的輸入輸出。
系統設計是一個從輸入獲得輸出的過程。這個階段涉及使用多層的抽象,將問題分解為可管理的組成部分,並且設計執行每個組成部分(子系統)的策略。
實現是將系統設計翻譯稱程序。為每個組成部分編寫獨立的程序,然后集成再一起工作。
測試確保代碼符合需求規范,並且排除錯誤。
部署是對軟件產品進行更新和改進。
示例:設計一個計算貸款支付程序。我們重點關注需求規范,分析,設計,實現和測試。
需求規范
程序滿足以下要求:
必須讓用戶輸入貸款利率、貸款額度、貸款年限
必須計算和顯示月支付額度和總支付額度
系統分析
輸出是月支付額和總支付額,可以通過貸款公式進行計算
總支付額 = 月支付額度 * 年限 * 12;
系統設計
分解出下面這些步驟:
step1:提示用戶輸入貸款利率、貸款額度、貸款年限
step2:對於年利率的輸入是一個百分比格式的數字,需要轉換為十進制數,輸入的利率是年利率,可以計算出月利率
step3:使用公式計算月支付額
step4:計算總支付額
編碼實現
package edu.cduestc.charpter1; import java.util.Scanner; public class ComputeLoan { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("請輸入貸款額度:"); double loanAmount = input.nextDouble(); System.out.println("請輸入貸款年限:"); int years = input.nextInt(); System.out.println("請輸入貸款利率,格式為:4.5,代表年利率為4.5%"); double interestRate = input.nextDouble(); double monthlyInterestRate = interestRate / 1200; double monthlyPayment = loanAmount * monthlyInterestRate / (1 - 1 / Math.pow(1 + monthlyInterestRate, years * 12)); double totalPayment = monthlyPayment * years * 12; System.out.println("月支付額:" + monthlyPayment); System.out.println("總支付額:" + totalPayment); } }
作業:
1.初始化a=3,b=4;請計算:
1) (a++)/3+(--b)*2-(a--)%6+(b++)*3-(b--)
2) (++b)*2-(a--)%4+(a++)*5-(--b)/2+(--a)
3) (a--)*6+(b++)/3-(--a)*2-(--b)*2+(++a)
2.初始化a=3,b=4;請計算:
1) a>b&(a++)>b&(--b)<a&(b++)>(a--);
2) b<=a|(b--)>(--a)|(++b)!=(a++)|(b--)==(a--)
3.成績score=80,如果成績大於等於60,輸出及格,如果成績大於等於70,輸出中,如果成績大於等於80,輸出良,如果成績大於等於90,輸出優秀,如果成績小於60,輸出不及格。
4.完成如下圖的功能
5.用戶輸入四位會員號:計算四位會員號的之和。提示:用/和%得到個位,十位,百位,千位
6.整錢兌零:將一個大額的錢分成較小的貨幣單位
該程序要求用戶輸入一個double類型的數值,該值是用美元和美分表示的總錢數,列出和總錢數等價的最大數量的dollar(美元)、quarter(2角5分)、dime(1角)、nickel(5分)和penny(1分)的數目,按照這個順序,從而使得硬幣最少。
7.將攝氏溫度轉為華氏溫度
華氏溫度=(9/5)* 攝氏溫度 + 32
8.計算飛機起飛所需的最短跑道長度
跑道長度 = v平方/2a;其中v為起飛速度,a為加速度
9.假設你每月向銀行存1000元乖乖,年利率為2%,那么月利率為 0.02 / 12,第一個月后,賬戶上的值就變為:
1000 * (1 + 0.02 / 12) = 1,001.67
第二個月就變為:
(1000 + 1,001.67) * (1 + 0.02 / 12) = ?
依次類推,編寫程序顯示6個月的賬戶總數(每個月顯示一行)
10.計算兩點(x1,y1) 和(x2,y2)之間的距離
面試常見問題
1.在底層,正數是以哪個碼存的?負數是以哪個碼存的?
2.Java有沒有goto?
3.用最有效率的方法算出2乘以8等於幾?
4.char型變量中能不能存貯一個中文漢字?為什么?
5.String是最基本的數據類型嗎?