目錄
Math 的 floor,round 和 ceil 方法實例比較
修飾符
Java語言提供了很多修飾符,主要分爲以下兩類:
- 訪問修飾符
- 非訪問修飾符
Java中,可以使用訪問控制符來保護對類、變量、方法和構造方法的訪問。Java 支持 4 種不同的訪問權限。
-
default (即默認,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。
-
private : 在同一類內可見。使用對象:變量、方法。 注意:不能修飾類(外部類)
-
public : 對所有類可見。使用對象:類、接口、變量、方法
-
protected : 對同一包內的類和所有子類可見。使用對象:變量、方法。 注意:不能修飾類(外部類)。
訪問控制和繼承
請注意以下方法繼承的規則:
-
父類中聲明爲 public 的方法在子類中也必須爲 public。
-
父類中聲明爲 protected 的方法在子類中要麼聲明爲 protected,要麼聲明爲 public,不能聲明爲 private。
-
父類中聲明爲 private 的方法,不能夠被繼承。
Protected可見性
protected的可見性在於兩點:
- 基類的 protected 成員是包內可見的,並且對子類可見;
- 若子類與基類不在同一包中,那麼在子類中,子類實例可以訪問其從基類繼承而來的protected方法,而不能訪問基類實例的protected方法。
例1:
=============================================================
package p1;
public class Father1 {
protected void f() {} // 父類Father1中的protected方法
}
package p1;
public class Son1 extends Father1 {}
package p11;
public class Son11 extends Father1{}
package p1;
public class Test1 {
public static void main(String[] args) {
Son1 son1 = new Son1();
son1.f(); // Compile OK ----(1)
son1.clone(); // Compile Error ----(2)
Son11 son = new Son11();
son11.f(); // Compile OK ----(3)
son11.clone(); // Compile Error ----(4)
}
}
對於上面的示例,首先看(1)(3),其中的f()方法從類Father1繼承而來,其可見性是包p1及其子類Son1和Son11,而由於調用f()方法的類Test1所在的包也是p1,因此(1)(3)處編譯通過。其次看(2)(4),其中的clone()方法的可見性是java.lang包及其所有子類,對於語句"son1.clone();"和"son11.clone();",二者的clone()在類Son1、Son11中是可見的,但對Test1是不可見的,因此(2)(4)處編譯不通過。
例2:
=================================================================
package p2;
class MyObject2 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
package p22;
public class Test2 extends MyObject2 {
public static void main(String args[]) {
MyObject2 obj = new MyObject2();
obj.clone(); // Compile Error ----(1)
Test2 tobj = new Test2();
tobj.clone(); // Complie OK ----(2)
}
}
對於(1)而言,clone()方法來自於類MyObject2本身,因此其可見性爲包p2及MyObject2的子類,雖然Test2是MyObject2的子類,但在Test2中不能訪問基類MyObject2的protected方法clone(),因此編譯不通過;對於(2)而言,由於在Test2中訪問的是其本身實例的從基類MyObject2繼承來的的clone(),因此編譯通過。
例3:
================================================
package p3;
class MyObject3 extends Test3 {
}
package p33;
public class Test3 {
public static void main(String args[]) {
MyObject3 obj = new MyObject3();
obj.clone(); // Compile OK ------(1)
}
}
對於(1)而言,clone()方法來自於類Test3,因此其可見性爲包p33及其子類MyObject3,而(1)正是在p33的類Test3中調用,屬於同一包,編譯通過。
例4:
===============================================================
package p4;
class MyObject4 extends Test4 {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package p44;
public class Test4 {
public static void main(String args[]) {
MyObject4 obj = new MyObject4();
obj.clone(); // Compile Error -----(1)
}
}
對於(1)而言,clone()方法來自於類MyObject4,因此其可見性爲包p4及其子類(此處沒有子類),而類Test4卻在包p44中,因此不滿足可見性,編譯不通過。
例5:
================================================================================
package p5;
class MyObject5 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
public class Test5 {
public static void main(String[] args) throws CloneNotSupportedException {
MyObject5 obj = new MyObject5();
obj.clone(); // Compile OK ----(1)
}
}
對於(1)而言,clone()方法來自於類MyObject5,因此其可見性爲包p5及其子類(此處沒有子類),而類Test5也在包p5中,因此滿足可見性,編譯通過。
例6:
=====================================================
package p6;
class MyObject6 extends Test6{}
public class Test6 {
public static void main(String[] args) {
MyObject6 obj = new MyObject6();
obj.clone(); // Compile OK -------(1)
}
}
對於(1)而言,clone()方法來自於類Test6,因此其可見性爲包p6及其子類MyObject6,而類Test6也在包p6中,因此滿足可見性,編譯通過。
例7:==================================================
=
package p7;
class MyObject7 extends Test7 {
public static void main(String[] args) {
Test7 test = new Test7();
test.clone(); // Compile Error ----- (1)
}
}
public class Test7 {
}
對於(1)而言,clone()方法來自於類Object,因此該clone()方法可見性爲包java.lang及其子類Test7,由於類MyObject7不在此範圍內,因此不滿足可見性,編譯不通過。
邏輯運算符&&
當使用與邏輯運算符&&時,在兩個操作數都爲true時,結果才爲true,但是當得到第一個操作爲false時,其結果就必定是false,這時候就不會再判斷第二個操作了。
public class LuoJi{
public static void main(String[] args){
int a = 5;//定義一個變量;
boolean b = (a<4)&&(a++<10);
System.out.println("使用邏輯與運算符的結果爲"+b);
System.out.println("a的結果爲"+a);
}
}
=========================================================
使用邏輯與運算符的結果爲false
a的結果爲5
解析: 該程序使用到了短路邏輯運算符(&&),首先判斷 a<4 的結果爲 false,則 b 的結果必定是 false,所以不再執行第二個操作 a++<10 的判斷,所以 a 的值爲 5。
增強for循環(for-each循環)
主要用於數組,能在不使用下標的情況下遍歷數組
for(聲明語句 : 表達式)
{
//代碼句子
}
- 聲明語句:聲明新的局部變量,該變量的類型必須和數組元素的類型匹配。其作用域限定在循環語句塊,其值與此時數組元素的值相等。
- 表達式:表達式是要訪問的數組名,或者是返回值爲數組的方法。
public class Test {
public static void main(String args[]){
int [] numbers = {10, 20, 30, 40, 50};
for(int x : numbers ){
System.out.print( x );
System.out.print(",");
}
System.out.print("\n");
String [] names ={"James", "Larry", "Tom", "Lacy"};
for( String name : names ) {
System.out.print( name );
System.out.print(",");
}
}
}
===============================================================
10,20,30,40,50,
James,Larry,Tom,Lacy,
switch - case 開關結構
switch case 執行時,一定會先進行匹配,如果沒有匹配項,則不執行指令;如果匹配成功則返回當前 case 的值,再根據是否有 break,若有break,直接跳出switch結構,若無break,從當前 case 開始,後續所有 case 的值都會輸出,無論是否匹配。
public class Test {
public static void main(String args[]){
int i = 1;
switch(i){
case 0:
System.out.println("0");
case 1:
System.out.println("1");
case 2:
System.out.println("2");
default:
System.out.println("default");
}
}
}
=============================================
1
2
default
裝箱、拆箱
(這裏沒有弄明白)
在實際開發過程中,我們經常會遇到需要使用對象,而不是內置數據類型的情形。爲了解決這個問題,Java 語言爲每一個內置數據類型提供了對應的包裝類。所有的包裝類(Integer、Long、Byte、Double、Float、Short)都是抽象類 Number 的子類。
這種由編譯器特別支持的包裝稱爲裝箱,所以當內置數據類型被當作對象使用的時候,編譯器會把內置類型裝箱爲包裝類。相似的,編譯器也可以把一個對象拆箱爲內置類型。Number 類屬於 java.lang 包。
public class Test{
public static void main(String args[]){
Integer x = 5; //當 x 被賦爲整型值時,由於x是一個對象,所以編譯器要對x進行裝箱
x = x + 10; //爲了使x能進行加運算,所以要對x進行拆箱。
System.out.println(x);
}
}
==============================================
15
Math 的 floor,round 和 ceil 方法實例比較
|
String類不可修改
String 類是不可改變的,所以你一旦創建了 String 對象,那它的值就無法改變了。如果需要對字符串做很多修改,那麼應該選擇使用 StringBuffer 和 StringBuilder類,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,並且不產生新的未使用對象。
StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在於 StringBuilder 的方法不是線程安全的(不能同步訪問)。由於 StringBuilder 相較於 StringBuffer 有速度優勢,所以多數情況下建議使用 StringBuilder 類。然而在應用程序要求線程安全的情況下,則必須使用 StringBuffer 類。
String s = "Google";
System.out.println("s = " + s);
s = "Runoob";
System.out.println("s = " + s);
===================================
Google
Runoob
從結果上看是改變了,但爲什麼說String對象是不可變的呢?
原因在於實例中的 s 只是一個 String 對象的引用,並不是對象本身,當執行 s = "Runoob"; 創建了一個新的對象 "Runoob",而原來的 "Google" 還存在於內存中。
測量時間
import java.util.*;
public class DiffDemo {
public static void main(String args[]) {
try {
long start = System.currentTimeMillis( );
System.out.println(new Date( ) + "\n");
Thread.sleep(5*60*10);
System.out.println(new Date( ) + "\n");
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println("Difference is : " + diff);
} catch (Exception e) {
System.out.println("Got an exception!");
}
}
}
System.out.println():調用系統類 System 中的標準輸出對象 out 中的方法 println()
值傳遞與引用傳遞
- 值傳遞:按值的拷貝傳遞,即傳遞後互不相關,java中原始數據類型均爲按值傳遞
- 引用傳遞:傳遞的引用的地址,傳遞前後變量只想同一個引用(即同一個內存空間,引用又叫起別名),非原始數據類型即引用數據類型是引用傳遞
方法的重載
函數名相同,參數列表不同(類型或個數等),java編譯器根據參數判斷調用哪一個函數。重載的方法必須擁有不同的參數列表。不能僅僅依據修飾符或者返回類型的不同來重載方法。
構造方法
- 每個類都有構造方法,當一個對象被創建時候,構造方法用來初始化該對象。
- 構造方法若無顯示定義,java編譯器提供默認構造方法,其訪問修飾符與類相同。
- 構造方法沒有返回值。
- 一個類可以有多個構造方法,名稱必須與類名相同
可變參數
JDK 1.5 開始,Java支持傳遞同類型的可變參數給一個方法。
方法的可變參數的聲明如下所示:
typeName... parameterName
在方法聲明中,在指定參數類型後加一個省略號(...) 。
一個方法中只能指定一個可變參數,它必須是方法的最後一個參數。任何普通的參數必須在它之前聲明。
public class VarargsDemo {
public static void main(String args[]) {
// 調用可變參數的方法
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
}
public static void printMax( double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return;
}
double result = numbers[0];
for (int i = 1; i < numbers.length; i++){
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("The max value is " + result);
}
}
============================================================
The max value is 56.5
The max value is 3.0
控制檯讀取與輸出
控制檯讀取
Java 的控制檯輸入由 System.in 完成。爲了獲得一個綁定到控制檯的字符流,你可以把 System.in 包裝在一個 BufferedReader 對象中來創建一個字符流。
下面是創建 BufferedReader 的基本語法:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader 對象創建後,便可以使用 read() 方法從控制檯讀取一個字符,或者用 readLine() 方法讀取一個字符串。
- int read( ) throws IOException : 讀取字符,每次調用 read() 方法,它從輸入流讀取一個字符並把該字符作爲整數值返回。 當流結束的時候返回 -1。該方法拋出 IOException。
- String readLine( ) throws IOException : 讀取字符串
//使用 BufferedReader 在控制檯讀取字符
import java.io.*;
public class BRRead {
public static void main(String args[]) throws IOException {
char c;
// 使用 System.in 創建 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("輸入字符, 按下 'q' 鍵退出。");
// 讀取字符
do {
c = (char) br.read();
System.out.println(c);
} while (c != 'q');
}
}
=================================================================================
將輸入的字符分行單個輸出,直至輸入q,程序終止
//使用 BufferedReader 在控制檯讀取字符
import java.io.*;
public class BRReadLines {
public static void main(String args[]) throws IOException {
// 使用 System.in 創建 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'end' to quit.");
do {
str = br.readLine();
System.out.println(str);
} while (!str.equals("end"));
}
}
========================================================================================
輸出讀取到的字符串
控制檯輸出
控制檯的輸出由 print( ) 和 println() 完成。這些方法都由類 PrintStream 定義,System.out 是該類對象的一個引用。
PrintStream 繼承了 OutputStream類,並且實現了方法 write()。這樣,write() 也可以用來往控制檯寫操作。但不常使用。
void write(int byteval)
讀寫文件
FileInputStream
該流用於從文件讀取數據,它的對象可以用關鍵字 new 來創建。
可以使用字符串類型的文件名來創建一個輸入流對象來讀取文件:
InputStream f = new FileInputStream("C:/java/hello");
也可以使用一個文件對象來創建一個輸入流對象來讀取文件。我們首先得使用 File() 方法來創建一個文件對象:
File f = new File("C:/java/hello"); InputStream out = new FileInputStream(f);
FileOutputStream
該類用來創建一個文件並向文件中寫數據。如果該流在打開文件進行輸出前,目標文件不存在,那麼該流會創建該文件。
使用字符串類型的文件名來創建一個輸出流對象:
OutputStream f = new FileOutputStream("C:/java/hello")
也可以使用一個文件對象來創建一個輸出流來寫文件。我們首先得使用File()方法來創建一個文件對象:
File f = new File("C:/java/hello"); OutputStream f = new FileOutputStream(f);
//文件名 :fileStreamTest2.java
import java.io.*;
public class fileStreamTest2 {
public static void main(String[] args) throws IOException {
File f = new File("a.txt");
FileOutputStream fop = new FileOutputStream(f);
// 構建FileOutputStream對象,文件不存在會自動新建
OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");
// 構建OutputStreamWriter對象,參數可以指定編碼,默認爲操作系統默認編碼,windows上是gbk
writer.append("中文輸入");
// 寫入到緩衝區
writer.append("\r\n");
// 換行
writer.append("English");
// 刷新緩存衝,寫入到文件,如果下面已經沒有寫入的內容了,直接close也會寫入
writer.close();
// 關閉寫入流,同時會把緩衝區內容寫入文件,所以上面的註釋掉
fop.close();
// 關閉輸出流,釋放系統資源
FileInputStream fip = new FileInputStream(f);
// 構建FileInputStream對象
InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
// 構建InputStreamReader對象,編碼與寫入相同
StringBuffer sb = new StringBuffer();
while (reader.ready()) {
sb.append((char) reader.read());
// 轉成char加到StringBuffer對象中
}
System.out.println(sb.toString());
reader.close();
// 關閉讀取流
fip.close();
// 關閉輸入流,釋放系統資源
}
}
參考:
https://www.runoob.com/java/java-operators.html