暫時寫到這裡
釋出記錄:2021年03月25日
推薦一個基礎自學網站:https://how2j.cn/
一、對象導論
對象導論對所有章節的内容進行了一個簡單的介紹。具體内容從第二章開始。
1.認識第一個縮寫:OOP,Object-oriented Programming
2.對象具有狀态、行為和辨別。
3.類描述了具有相同特性(資料元素)和行為(功能)的對象集合,類實際上就是一個資料類型。
4.認識第二個縮寫:UML,Unified Modelling Language
5.聚合:組合是動态發生的。組合是has-a(擁有)關系
6.繼承:基類與導出類(子類,或者稱為繼承類)的關系是is-a(是一個)關系
二、一切都是對象
1.資料存儲的位置
存儲資料的五個位置 | |||
序号 | 名稱 | 位置 | 特點 |
1 | 寄存器 | 處理器内部 | ①存儲速度最快,寄存器存儲 ②寄存器數量有限,無法直接控制 ③其按需求配置設定 |
2 | 堆棧 | 通用RAM(随機通路存儲器) | ①存儲速度僅次于存儲器,通過堆棧指針可以從處理器那裡獲得直接支援 ②堆棧指針向下移動,配置設定新記憶體;反之,釋放記憶體 ③使用前提,建立程式必須知道堆棧内所有項的生命周期。失去了靈活性,java對象不存儲在這裡 |
3 | 堆 | 通用的記憶體池(位于RAM區) | ①存放java對象 ②不需要知道存儲的資料的生命周期,具有配置設定存儲的靈活性 ③缺點:存儲配置設定和清理使用的時間需要更多 |
4 | 常量存儲 | 程式代碼内部或者ROM(隻讀存儲器) | ①安全,保持資料不會被改變 |
5 | 非RAM存儲 | 其它媒介的事物 | ①可以不受程式的任何控制,程式是否運作都可存在 ②基本使用例子如流對象和持久化對象 |
2.基本類型的學習
3.作用域:由花括号的位置決定,它決定了在其内定義的變量名的可見性和生命周期。
4.對象的作用域:不具備和基本類型一樣的生命周期,java有一個垃圾回收器,用來監視用new建立的所有對象,并辨識那些不會再被引用的對象
5.字段(也稱為資料成員,成員變量),方法(也稱為成員函數),它們都是類中的元素。
6.static關鍵字:
作用:為某特定域配置設定單一存儲空間,同時能夠通過類名直接調用其方法
描述:static修飾的成員變量在類運作時就會執行,即配置設定存儲空間,且僅會執行一次
static修飾的方法中不允許有this關鍵字,其方法可以通過類名直接調用
7.java注釋簡要說明,包括标簽示例說明
8.通過cmd運作指令生成程式的注釋文檔,文法如下
javadoc -d Mydoc -author -version 類名.java
說明:Mydoc自定義檔案夾的名稱
類名是需要生成文檔的類的名稱
實作前提:在該檔案的目錄下運作cmd
9.編碼風格說明
三、操作符
1.用一張表來顯示所有的操作符
2.直接常量的習慣表示:long型,後面加L;float型,後面加F;double型,後面加D
3.進制數的表示:二進制,用0和1表示
八進制,字首是0,後續是0-7
十進制,用0-9表示
十六進制,字首是0x或者0X,後續是0-9或小寫(或大寫)的A-F
4.進制數之間的互相轉換
5.窄化轉換:将能容納更多資訊的資料類型轉換成無法容納那麼多資訊的類型,可能面臨資訊丢失的危險。如把long型轉成int型時。
6.拓展轉換:與窄化轉換相反,但是它不會造成任何資訊的丢失。
7.類型轉換文法:(轉換的類型名稱)轉換的值。該轉換方式下,浮點型轉成整型時是直接去掉小數部分。
8.注意的問題:在類型轉換中,有可能會造成結果溢出,但是這個不會報出異常,需要特别注意。
9.補充舉例說明移位操作符的計算方式
package com.study.thinking.in.java.part3;
public class PartDemo3 {
public static void main(String[] args) {
// 以下測試中,對于int型都是低5位數有效,long型低6位有效
// 左移在低位均是補0
int a = 1;
// 說明:最高位0始終不變
// 正數1的二進制數表示為1
System.out.println(Integer.toBinaryString(a));
a <<= 5;
// 左移5位低位補0,結果就是100000,對應的十進制數就是32(即目前的a值)
System.out.println(Integer.toBinaryString(a));
int a1 = -1;
// 說明:最高位1始終不變
// 步1:二進制:1000 0000 0000 0000 0000 0000 0000 0001
// 步2:二進制補碼:1111 1111 1111 1111 1111 1111 1111 1110
// 步3:二進制補碼加1:1111 1111 1111 1111 1111 1111 1111 1111
System.out.println(Integer.toBinaryString(a1));
a1 <<= 5;
// 步4:左移之後變為(低位補0):1111 1111 1111 1111 1111 1111 1110 0000
// 步5:二進制補碼:1000 0000 0000 0000 0000 0000 0001 1111
// 步6:二進制補碼加1:1000 0000 0000 0000 0000 0000 0010 0000,結果值就是-32
System.out.println(Integer.toBinaryString(a1));
int b = 1;
b >>= 5;
// 說明:最高位0始終不變
// 步1:二進制:0000 0000 0000 0000 0000 0000 0000 0001
// 步2:右移之後變為(整數最高位補0):0000 0000 0000 0000 0000 0000 0000 0000(舍棄步3的最後5位),結果值就是-1
System.out.println(Integer.toBinaryString(b));
int c = -1;
c >>= 5;
// 說明:最高位1始終不變
// 步1:二進制:1000 0000 0000 0000 0000 0000 0000 0001
// 步2:二進制補碼:1111 1111 1111 1111 1111 1111 1111 1110
// 步3:二進制補碼加1:1111 1111 1111 1111 1111 1111 1111 1111
// 步4:右移之後變為(負數最高位補1):1111 1111 1111 1111 1111 1111 111(舍棄步3的最後5位)
// 步5:二進制補碼:1000 0000 0000 0000 0000 0000 000
// 步6:二進制補碼加1:1000 0000 0000 0000 0000 0000 001,結果值就是-1
System.out.println(Integer.toBinaryString(c));
// 無符号位則均是補0
int d = -1;
d >>>= 5;
// 步1:二進制:1000 0000 0000 0000 0000 0000 0000 0001
// 步2:二進制補碼:1111 1111 1111 1111 1111 1111 1111 1110
// 步3:二進制補碼加1:1111 1111 1111 1111 1111 1111 1111 1111
// 步4:右移之後變為(最高位補0):0000 0111 1111 1111 1111 1111 111(舍棄步3的最後5位)
// 步5:二進制補碼:1111 1000 0000 0000 0000 0000 000
// 步6:二進制補碼加1:111 1100 0000 0000 0000 0000 0001,結果值就是134217727
System.out.println(Integer.toBinaryString(d));
// 無符号位則均是補0
int e = 1;
e >>>= 5;
// 步1:二進制:0000 0000 0000 0000 0000 0000 0000 0001
// 步2:右移之後變為(最高位補0):0000 0000 0000 0000 0000 0000 000(舍棄步3的最後5位),結果值就是0
System.out.println(Integer.toBinaryString(e));
//總結:左右移位時,負整數需要先換成補碼加1再進行移位,移位之後,再換成補碼加1即得到最後的結果。而正整數直接二進制移位即可
}
}
==================================================================================================================================================================================
a = 1 二進制數: 1
a = 1 左移位5位: 100000
a1 = -1 二進制數(補碼加1的形式): 11111111111111111111111111111111
a1 = -1 左移位5位: 11111111111111111111111111100000
c = 1 有符号右移位5位: 0
c = -1 有符号右移位5位: 11111111111111111111111111111111
d = -1 無符号右移位5位: 111111111111111111111111111
e = 1 無符号右移位5位: 0
四、控制執行流程
1.條件語句,根據條件執行相應的語句
001.if語句文法
if(Boolean-expression)
statement;
002.if-else語句文法
if(Boolean-expression)
statement;
else
statement;
003.switch語句文法
switch(integral-selector){
case integral-value1:
statement;
break;
case integral-value2:
statement;
break;
case integral-value3:
statement;
break;
// ...
default:
statement;
}
2.疊代語句:控制循環的語句。主要有以下三種:
(1)while循環,文法:
while(Boolean-expression)
statement;
(2)do...while循環,文法:
do
statement;
while(Boolean-expression)
(3)for循環,文法:
for(initialization;Boolean-expression;step)
statement;
3.無限循環的兩種表達方式
(1)while(true)statement;
(2)for(;;) statement;
4.周遊數組的兩種方式
001.for循環周遊,文法:
int[] list = new int[10];
for(int i = 0; i < list.length; i++){
System.out.println(list[i]);
}
002.Foreach循環周遊,文法:
int[] list = new int[10];
for(int i: list){
System.out.println(i);
}
5.結束控制語句的幾種方法
(1)正常執行完所有語句
(2)可以使用break,continue,return結束語句的執行,三者差別如下
001.break,可用于條件語句和循環語句中,表示結束目前條件語句的執行或者循環語句的執行
002.continue,隻可用于循環語句中,表示跳過本次循環,執行下一次循環
003.return,均可用,表示結束該方法體的執行,在最接近的同一個大括号中,return之後不允許再有執行語句
錯誤示例如下:
// 這是一個錯誤的例子
for(int i = 0;i<10;i++{
if(i == 3){
return;
System.out.println(i);
}
}
6.多層循環中break,continue,return的用處:
// 三層嵌套示例
label1:
for(int i=0;i < 3;i++) {
if(i == 2)
break label1;// 結束标記标簽label1以下的所有循環
label2:
for(int j = 0; j < 3; j ++) {
if(j == 1)
continue label1; // 跳出j循環,直接執行i++
System.out.println("===============分割線 i ="+i+" j = "+ j+" =================");
for(int k = 0; k < 3; k ++) {
if(k == 0)
continue; // 跳過k == 0,執行k == 1
if(k == 2)
break; // 退出k循環
// 下面列印語句隻執行了一次,即 k == 1時
System.out.println(" k == "+k);
}
}
}
===================測試結果=====================
===============分割線 i =0 j = 0 =================
k == 1
===============分割線 i =1 j = 0 =================
k == 1
總結:
01.break,結束一個循環體,break label,結束一個标簽内的所有循環體;
02.continue,跳過一次循環,continue label,跳到指定标簽開始下一次循環;
03.return,結束方法體。
7.逗号操作符在循環語句中的作用:通過使用逗号操作符,在for循環語句中定義多個變量,但是這有一個前提:變量的類型應該是相同的。
8.學習示例彙總如下:
Scanner scanner = new Scanner(System.in);
// 練習1:列印1到100的整數
for(int i = 1; i< 101; i++){
System.out.println(i);
}
// 練習2:産生25個随機整數,從第二個開始,和前一個比較大小,分别列印出來
int[] list = new int[25];
for (int i = 0; i < list.length; i++) {
// Math.random()産生0 - 1的随機浮點數
list[i] = (int)(Math.random()*26);
// 從第2個開始和前一個比較
if(i > 0){
if(list[i] > list[i-1])
System.out.println(list[i]+" > "+list[i-1]);
else
System.out.println(list[i]+" <= "+list[i-1]);
}
}
// 練習3:兩個嵌套for循環和取餘方式檢測輸入的整數是否是素數(素數是隻能被自身和1整除)
label:
for(int i = 0; i < 10; i++){
System.out.println("輸入一個整數:");
int num = scanner.nextInt();
for(int j = 2; j < num; j++){
if(num % i == 0){
System.out.println(num+"這個數不是素數");
break label;// 如果輸入的數字不是素數,結束執行
}
}
}
//練習4:斐波那契數列,從第三個數開始,均是前兩個數之和,輸入一個整數,輸出斐波那契數列的參數個數:如輸入5,就有5個數
System.out.println("輸入一個整數:");
int num = scanner.nextInt();
System.out.println("斐波那契數列為:");
int firstNum = 1;
int secondNum = 1;
for(int i = 0;i < num; i++){
if(i < 2){
System.out.print(firstNum + "\t");
} else{
int threeNum = firstNum + secondNum;
System.out.print(threeNum + "\t");
firstNum = secondNum;
secondNum = threeNum;
}
}
// 練習5:4位數字的所有吸血鬼數字(位數為偶數的數字,如2,4,6位數數;同時組成的數字兩兩組合相乘可以得到該數)
for(int i = 1000; i< 10000; i++){
// 剔除後面兩個是0的情況
if(i % 100 != 0){
// 轉成字元串
String str = String.valueOf(i);
Label:
for(int k = 11; k < 100; k++){
int num = i % k;
// 對整除結果進行判斷
if(num == 0){
// 擷取對應的數字并轉成字元串
int value = i / k;
String[] strs = new String[4];
strs[0] = String.valueOf(k % 10);
strs[1] = String.valueOf(k / 10);
strs[2] = String.valueOf(value % 10);
strs[3] = String.valueOf(value / 10);
// 組合成字元串,如果相等即找到了,如果不等,則繼續
for (int j = 0; j < strs.length; j++) {
for (int m = 0; m < strs.length; m++) {
if(j != m){
for (int m1 = 0; m1 < strs.length; m1++) {
if(m != m1 && j != m1){
for (int m2 = 0; m2 < strs.length; m2++) {
if(m2 != m && j != m2 && m2 !=m1){
String res = strs[j]+strs[m]+strs[m1]+strs[m2];
if(res.equals(str)){
//System.out.println("res = "+res + " and str = "+str);
System.out.println(i+"是吸血鬼數字,"+i +" = "+k+"*"+value);
break Label;
}
}
}
}
}
}
}
}
}
}
}
}
五、初始化與清理
1.類的基礎知識
A.構造器:確定對象的建立能夠被初始化。包括了兩類構造器
01.無參構造器(預設構造器,如果程式設計過程中不寫構造器,系統預設建立一個無參構造器)
02.有參構造器(也可以了解為構造器的重載)
注意:構造器的名稱應該和類名完全一緻,構造器也是一種方法,稱為構造方法。
B.方法的重載:方法名相同,但是參數清單不完全相同,這樣的方法稱為方法的重載。
注意點:01.在方法名相同的情況下,重載的參數清單一樣,但是順序不同也是方法的重載,但是在程式設計過程中不建議這樣建立重載方法
02.根據傳回值類型來區分方法重載是行不通的,因為有時我們的需求不需要使用到傳回值,而隻是方法的執行過程
C.this關鍵字
01.使用範圍:隻能在非靜态方法(包括構造方法)内調用
02.使用建議:在同一個類中,非靜态方法中調用其它方法,不需要寫this
03.構造器說明:this在構造器中指代目前對象,通過它可以直接調用其它構造方法,但是隻能調用一次構造方法且必須寫在第一行(預設情況下調用父類的預設構造方法,一般不寫出來)
D.static關鍵字
01.static方法的内部不能調用非靜态的方法,反過來可以。
02.static修飾的方法或變量,可以通過類名直接通路
03.static修飾的方法中全局變量必須是static修飾的
04.static不能用于局部變量的修飾
package com.study.thinking.in.java.part5;
public class Student {
static int id;
String sudentID;
// 無參構造方法(無參構造器),即預設構造器,如果隐藏不寫,并且不重寫構造器,那麼編譯時,自動建立構造器,如果已經存在重寫的構造器,将不再建立無參構造方法
public Student(){
// 下面是父類的預設構造方法,如果在該構造器中沒有調用其它構造方法,它預設存在,并且可以忽略不寫出來;如果已經寫出,下面将不能再用this調用構造方法
// super();
// this指代student對象本身,它有一個重載的構造方法,是以以下可以直接使用
this("preston",20);
// 錯誤示範:this調用構造方法隻能一次且必須寫在第一行
// this("David",18);
// this指代student對象本身,對它的id值進行初始化
this.sudentID = "2021001";
System.out.println("沒有指明名字和年齡的學生");
}
// 有參構造方法(有參構造器),名稱與類名一緻,當寫了有參構造方法,如果不寫無參構造方法,将無法通過無參構造建立對象
public Student(String name,int age){
System.out.println("學生姓名是:"+name+",學生年齡是:"+age);
}
public static void main(String[] args) {
// 在static修飾的方法中,不能使用this,并且不能調用非靜态的方法,以下是錯誤示例
// subject("English");
Student student = new Student();
// static修飾的方法通路static修飾的方法
describeStudentId();
}
public static void describeStudentId(){
System.out.println(id+"是學生編号");
}
// 方法:科目名稱
public void subject(String name){
System.out.println(name+"科");
}
// 方法重載1:科目分數
public void subject(int score){
System.out.println(score+"分");
}
// 方法重載2:科目名稱和分數
public void subject(String name,int score){
// 調用同類中的方法,不需要寫this
// this.subject("English");可以省略this
subject("English");
System.out.println(name+"科 "+score+"分");
}
// 錯誤範例:與上面的方法沖突,不是方法的重載
// public int subject(String name,int score){ }
}
class Test5{
public static void main(String[] args) {
// Student重寫了構造方法,不寫無參構造方法,無法在通過無參構造建立對象,以下内容報錯
//Student student = new Student();
// id被static修飾可以直接通過類名通路
Student.id = 5;
// 方法被static修飾可以直接通過類名通路
Student.describeStudentId();
}
}
2.java中對象垃圾回收的三個知識要點:
01.對象可能不被垃圾回收
02.垃圾回收并不等于“折構”
03.垃圾回收隻與記憶體有關
注:java虛拟機在并未面臨記憶體耗盡的情況下,它是不會浪費時間去執行垃圾回收以恢複記憶體的。
3.幾種垃圾回收技術的初步認識
01.引用計數,是一種簡單但速度很慢的垃圾回收技術。每一個對象都含有一個引用計數器,有引用接至對象時,引用計數加1,離開或被置為null時,減1。垃圾回收期會在含有全部對象的清單上進行周遊,當發現某個對象的引用計數為0時,就釋放其占用的空間。
缺陷:如果對象之間存在循環引用,可能出現“對象應該被回收,但引用計數卻不為零”。
02.自适應的垃圾回收技術,關鍵詞:分代的、停止-複制、标記-清掃。
4.初始化:成員初始化、指定初始化、構造器初始化、靜态資料的初始化、顯示的靜态初始化、非靜态執行個體初始化、數組初始化
總結:初始化是在編譯時就進行的,它會将所有的初始化内容進行初始化,無法進行初始化的将會報出編譯時異常
01.成員變量的初始化,基本類型會進行預設指派
02.指定初始化是直接給予指派操作
03.構造器初始化,構造器的内容初始化順序是根據執行構造方法的先後順序決定
04.靜态資料的初始化是發生在類運作時,是最先進行初始化的
05.顯示的靜态初始化就是構造代碼塊的初始化
06.非靜态執行個體初始化就是對象的初始化
07.數組初始化,數組使用前必須進行初始化
08.可變參數:參數個數或類型未知時使用。當知道類型,未知個數,則應該指明類型,否則使用Object。表示方法示例:
public void study(Object...args){
// 方法體
}
5.枚舉類型:關鍵字enum修飾類名,常用作具有固定選擇,以坦克大戰方向舉例如下:
package com.study.thinking.in.java.part5;
// 枚舉類:四個方向
public enum Direction {
// 左右上下四個方向
LEFT,RIGHT,UP,DOWN
}
class Tank{
public static void main(String[] args) {
new Tank().moveDirection(Direction.DOWN);
}
private void moveDirection(Direction direction){
// 判斷移動方向
switch (direction){
case UP:
System.out.println("向上運動");
break;
case DOWN:
System.out.println("向下運動");
break;
case RIGHT:
System.out.println("向右運動");
break;
case LEFT:
System.out.println("向左運動");
break;
}
}
}
六、通路權限控制
1.包名:必須是獨一無二的(根據域名建立),它是類庫單元。寫在非注釋第一行
2.引入包:通過關鍵字import+包名(全局名稱)導入使用,寫在包名下面
3.四種通路權限
七、複用類(兩種方式實作:一個是組合,一個是繼承)
1.組合文法:(組合:就是在新類中通過建立已有類對象,實作對已有類的使用,通俗的講就是建立類的執行個體對象,進而實作對類的功能的調用),如下例子
/**
* 組合類使用範例
*/
public class CombineClassDemo {
private String message;
private OldCombineClass oldCombineClass = new OldCombineClass();
public String toString(){
return "message = " + message+",\t"+
"oldCombineClass = "+oldCombineClass;
}
// 測試:通過建立對象實作對類的使用
public static void main(String[] args) {
CombineClassDemo combineClassDemo = new CombineClassDemo();
System.out.println(combineClassDemo);
}
}
class OldCombineClass{
private String message;
public OldCombineClass(){
System.out.println("OldCombineClass()");
message = "Constructed";
}
public String toString(){
return message;
}
}
==============================輸出結果=======================================
OldCombineClass()
message = null, oldCombineClass = Constructed
2.繼承文法:(繼承:根據已有的類建立新類,對于新類隻需将拓展的新方法實作即可,對于已有方法可以直接調用(在預設修飾符均為公共的情況下)),如下例子
繼承類:稱為導出類,也稱為子類(自己習慣稱為子類)
被繼承類:稱為基類,也稱為父類(自己習慣稱為子類)
/**
* 繼承使用範例
* 繼承類,即導出類
*/
public class ExtendsClassDemo extends ExtendsClass{
// 測試:通過繼承實作對類的使用
public static void main(String[] args) {
// 預設調用基類的toString()方法
ExtendsClassDemo extendsClassDemo = new ExtendsClassDemo();
System.out.println(extendsClassDemo);
}
}
// 被繼承類,即基類
class ExtendsClass{
private String message;
public ExtendsClass(){
System.out.println("OldCombineClass()");
message = "Constructed";
}
public String toString(){
return message;
}
}
===========================================輸出結果===================================
OldCombineClass()
Constructed
3.基類(父類)的初始化:實行原則是:從最頂級的父類開始、直至導出類(即子類)依次初始化,下面這個範例可以很好地展現出來
說明:01.預設情況下,在調用子類的構造方法建立子類對象時,均會調用基類的無參構造方法進行基類的初始化,該語句是super(),如果寫出來要求必須寫在第一行,且同一個調用的構造方法中,隻能寫一次,無論是否有無參數
02.如果在調用子類的構造方法中給父類進行傳參,如例子中的super(str)則要求基類中存在對應的有參構造,否則将報錯
03.在預設情況下,類會自動建立一個無參構造方法,該方法沒有任何具體内容;但是當建立的類中已有有參構造方法,無參構造方法将不會預設建立,是以需要使用的話,需要在建立類時手動建立
總結:01.基類的無參構造方法在預設情況下均會被調用
02.在建立基類時,如果有有參構造方法存在,應該寫上無參構造方法
// 導出類,即子類
public class InitClassDemo extends Person{
/**
* 同一個類中,不同的構造方法之間不能互相調用,如該例中有參構造和無參構造不能互相調用
*
* @param str 字元串
*/
public InitClassDemo(String str){
// 初始化基類的有參構造必須寫出來,super("")構造方法必須寫在調用的構造方法中的第一行,而且隻能寫在構造方法中
super(str);
System.out.println(str+"這是人類中的一員,名字叫preston2");
}
public InitClassDemo(){
// super()是預設存在的,如果要寫出來,必須寫在構造方法的第一行,而且隻能寫在構造方法中
// super();
System.out.println("這是人類中的一員,名字叫preston");
System.out.println("-------------------------分割線------------------------");
// 建立對象是允許的
new InitClassDemo("有參構造:");
// 調用構造方法是錯誤的
// InitClassDemo("");
}
public static void main(String[] args) {
// 無參構造方法建立導出類對象,基類實作初始化,這裡建立的是匿名對象
new InitClassDemo();
}
}
// 既是導出類,也是基類
class Person extends Humen{
public Person(){
System.out.println("這是人類中的一員");
}
public Person(String str){
super(str);
System.out.println(str+"這是人類中的一員");
}
}
// 基類
class Humen{
public Humen(){
System.out.println("這是人類");
}
public Humen(String str){
System.out.println(str+"這是人類22");
}
}
==========================測試結果===============================
這是人類
這是人類中的一員
這是人類中的一員,名字叫preston
-------------------------分割線------------------------
有參構造:這是人類22
有參構造:這是人類中的一員
有參構造:這是人類中的一員,名字叫preston2
4.代理的文法:(略,也是可以實作對一個類的各種方法使用)
現在java可以通過Proxy實作,基礎知識應用到的是反射,後面章節學習到再寫。
也有工具可以直接生成,書上說JetBrains Idea IDE可以自動生成
上述的三種使用複用類的方法通常是結合使用的。
5.組合與繼承的選擇使用原則
01.使用繼承:兩個類的關系是(is-a關系),即該類是另一個類的延伸或拓展,是一種從屬關系,形象比喻如:汽車和交通工具的關系
02.使用組合:兩個類的關系是(has-a關系),即該類和另一個類存在相同部分,是一種交集關系。形象比喻如:汽車輪子和汽車的關系
6.向上轉型:由導出類轉成基類,即子類轉成父類。因為在繼承圖上是向上移動的,是以稱為向上轉型。
7.final關鍵字
01.修飾資料,如果是變量,其數值恒定不變,稱為常量;如果是對象,其指向的對象恒定(僅是指定引用的對象恒定,但是對象的内容是可以改變的)
02.空白final,可以先定義,但是在初始化時,構造函數中必須給其進行初始化;注意,如果使用static修飾final則不行(因為static修飾的變量先于構造方法執行),如下
03.修飾參數,參數将不允許修改,但是可以使用
public class ExampleFinalDemo {
private final int i;
// 報錯,未進行初始化
//private static final int j;
public ExampleFinalDemo(){
i = 1;
System.out.println("i = "+i);
print(5);
}
public void print(final int num){
System.out.println("num = "+num);
// 報錯,提示不能修改
// num = num+2;
// System.out.println("num == "+num);
}
public static void main(String[] args) {
new ExampleFinalDemo();
}
}
04.final修飾的方法不能被子類重寫
05.final修飾的類不能被繼承
8.類的初始化順序
01.加載類時,優先初始化父類中的靜态變量和靜态代碼塊。其中靜态變量和靜态代碼塊的執行順序是按語句的先後順序依次執行
02.其次初始化子類中的靜态變量和靜态代碼塊。其中靜态變量和靜态代碼塊的執行順序是按語句的先後順序依次執行
03.然後初始化父類中的其它變量和代碼塊,按先後順序依次執行,然後執行父類構造方法中的其它代碼
04.再然後初始化子類中的其它變量和代碼塊,按先後順序依次執行,然後執行子類構造方法中的其它代碼
運用代碼示範如下:
public class ExampleInitDemo extends ExampleClass {
private ExampleTest1 test1 = new ExampleTest1("執行順序09:");
static {
new ExampleTest1("執行順序03:");
}
private static ExampleTest1 test2 = new ExampleTest1("執行順序04:");
{
new ExampleTest1("執行順序10:");
}
static {
new ExampleTest1("執行順序05:");
}
{
new ExampleTest1("執行順序11:");
}
public ExampleInitDemo(){
new ExampleTest1("執行順序12:");
}
public static void main(String[] args) {
new ExampleInitDemo();
}
}
class ExampleClass{
private ExampleTest1 test1 = new ExampleTest1("執行順序06:");
private static ExampleTest1 test2 = new ExampleTest1("執行順序01:");
static {
new ExampleTest1("執行順序02:");
}
{
new ExampleTest1("執行順序07:");
}
public ExampleClass(){
new ExampleTest1("執行順序08:");
}
}
class ExampleTest1{
public ExampleTest1(String str){
System.out.println(str+"測試用例進行初始化了");
}
}
===================================示範結果============================================
執行順序01:測試用例進行初始化了
執行順序02:測試用例進行初始化了
執行順序03:測試用例進行初始化了
執行順序04:測試用例進行初始化了
執行順序05:測試用例進行初始化了
執行順序06:測試用例進行初始化了
執行順序07:測試用例進行初始化了
執行順序08:測試用例進行初始化了
執行順序09:測試用例進行初始化了
執行順序10:測試用例進行初始化了
執行順序11:測試用例進行初始化了
執行順序12:測試用例進行初始化了
八、多态
1.
二十二、圖形使用者化界面
1.視窗(JFrame)
01.視窗的建立及其基礎設計:具有如下兩種方式實作視窗界面的顯示
/**
* 普通寫法顯示視窗
*/
public class JFrameDemo {
public static void main(String[] args) {
// 視窗的對象建立
JFrame frame = new JFrame();
// 視窗的标題設定
frame.setTitle("測試用例");
// 元件的名字(圖形顯示并未觀察到)
frame.setName("這是視窗");
// 視窗的尺寸設定
frame.setSize(1000,800);
// 視窗的在螢幕出現的位置設定
frame.setLocation(new Point(100,50));
// 關閉視窗時的操作,JFrame.EXIT_ON_CLOSE表示視窗會關閉,同時推出程式,JFrame.NORMAL表示正常顯示,不會關閉,JFrame.DISPOSE_ON_CLOSE表示會關閉目前視窗
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// 顯示視窗,true顯示,可見,false不顯示,不可見
frame.setVisible(true);
}
}
/**
* 繼承方式顯示視窗
*/
class MyJFrame extends JFrame{
public static void main(String[] args) {
new MyJFrame();
}
public MyJFrame(){
setTitle("視窗标題");
setSize(1000,800);
// 視窗不可以放大
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}