數(shù)據(jù)類型
-
數(shù)據(jù)類型分類
基本數(shù)據(jù)類型:包括 整數(shù) 鹊杖、 浮點數(shù) 、 字符 扛芽、 布爾
引用數(shù)據(jù)類型:包括 類 骂蓖、 數(shù)組 、 接口
基本數(shù)據(jù)類型:四類八種數(shù)據(jù)類型 關(guān)鍵字 內(nèi)存占用 取值范圍 字節(jié)型 byte 1個字節(jié) -128~127 短整型 short 2個字節(jié) -32768~32767 整型 int(默認) 4個字節(jié) -231次方~2的31次方-1 長整型 long 8個字節(jié) -2的63次方~2的63次方-1 單精度浮點數(shù) float 4個字節(jié) 1.4013E-45~3.4028E+38 雙精度浮點數(shù) double(默認) 8個字節(jié) 4.9E-324~1.7977E+308 字符型 char 2個字節(jié) 0-65535 布爾類型 boolean 1個字節(jié) true胸哥,false 注意:
long類型:建議數(shù)據(jù)后加L表示涯竟。
float類型:建議數(shù)據(jù)后加F表示。 -
自動轉(zhuǎn)換規(guī)則
byte空厌、short庐船、char‐‐>int‐‐>long‐‐>float‐‐>double
-
強制轉(zhuǎn)換
將 1.5 賦值到 int 類型變量會發(fā)生什么?產(chǎn)生編譯失敗嘲更,肯定無法賦值筐钟。
? int i = 1.5; // 錯誤
強制類型轉(zhuǎn)換:將 取值范圍大的類型 強制轉(zhuǎn)換成 取值范圍小的類型 。 比較而言赋朦,自動轉(zhuǎn)換是Java自動執(zhí)行的篓冲,而強制轉(zhuǎn)換需要我們自己手動行李破。 轉(zhuǎn)換格式 :數(shù)據(jù)類型 變量名 = (數(shù)據(jù)類型)被轉(zhuǎn)數(shù)據(jù)值;
? int i = (int)1.5
/* 強制類型轉(zhuǎn)換 1. 特點:代碼需要進行特殊的格式處理壹将,不能自動完成嗤攻。 2. 格式:范圍小的類型 范圍小的變量名 = (范圍小的類型) 原本范圍大的數(shù)據(jù); 注意事項: 1. 強制類型轉(zhuǎn)換一般不推薦使用,因為有可能發(fā)生精度損失诽俯、數(shù)據(jù)溢出妇菱。 2. byte/short/char這三種類型都可以發(fā)生數(shù)學運算,例如加法“+”. 3. byte/short/char這三種類型在運算的時候暴区,都會被首先提升成為int類型闯团,然后再計算。 4. boolean類型不能發(fā)生數(shù)據(jù)類型轉(zhuǎn)換 */ public class Demo02DataType { public static void main(String[] args) { // 左邊是int類型仙粱,右邊是long類型房交,不一樣 // long --> int,不是從小到大 // 不能發(fā)生自動類型轉(zhuǎn)換伐割! // 格式:范圍小的類型 范圍小的變量名 = (范圍小的類型) 原本范圍大的數(shù)據(jù); int num = (int) 100L; System.out.println(num); // long強制轉(zhuǎn)換成為int類型 int num2 = (int) 6000000000L; System.out.println(num2); // 1705032704 // double --> int候味,強制類型轉(zhuǎn)換 int num3 = (int) 3.99; System.out.println(num3); // 3,這并不是四舍五入口猜,所有的小數(shù)位都會被舍棄掉 char zifu1 = 'A'; // 這是一個字符型變量负溪,里面是大寫字母A System.out.println(zifu1 + 1); // 66,也就是大寫字母A被當做65進行處理 // 計算機的底層會用一個數(shù)字(二進制)來代表字符A济炎,就是65 // 一旦char類型進行了數(shù)學運算川抡,那么字符就會按照一定的規(guī)則翻譯成為一個數(shù)字 byte num4 = 40; // 注意!右側(cè)的數(shù)值大小不能超過左側(cè)的類型范圍 byte num5 = 50; // byte + byte --> int + int --> int int result1 = num4 + num5; System.out.println(result1); // 90 short num6 = 60; // byte + short --> int + int --> int // int強制轉(zhuǎn)換為short:注意必須保證邏輯上真實大小本來就沒有超過short范圍须尚,否則會發(fā)生數(shù)據(jù)溢出 short result2 = (short) (num4 + num6); System.out.println(result2); // 100 } }
運算符和變量崖堤、常量
-
+=符號的擴展
public static void main(String[] args){ short s = 1; s+=1; System.out.println(s); }
分析: s += 1 邏輯上看作是 s = s + 1 計算結(jié)果被提升為int類型,再向short類型賦值時發(fā)生錯誤耐床,因為不能將取值范圍 大的類型賦值到取值范圍小的類型胯甩。但是, s=s+1進行兩次運算 偎箫, += 是一個運算符怜森,只運算一次想许,并帶有強制轉(zhuǎn)換的特點漱凝, 也就是說 s += 1 就是 s = (short)(s + 1) ,因此程序沒有問題編譯通過,運行結(jié)果是2
-
常量和變量的運算
public static void main(String[] args){ byte b1=1; byte b2=2; byte b3=1 + 2; byte b4=b1 + b2; System.out.println(b3); System.out.println(b4); }
分析: b3 = 1 + 2 掀亥, 1 和 2 是常量撮竿,為固定不變的數(shù)據(jù)授账,在編譯的時候(編譯器javac)纳击,已經(jīng)確定了 1+2 的結(jié)果并沒 有超過byte類型的取值范圍,可以賦值給變量 b3 换团,因此 b3=1 + 2 是正確的。
反之磷醋, b4 = b2 + b3 , b2 和 b3 是變量邓线,變量的值是可能變化的骇陈,在編譯的時候授瘦,編譯器javac不確定b2+b3的結(jié)果是什 么提完,因此會將結(jié)果以int類型進行處理挡篓,所以int類型不能賦值給byte類型,因此編譯失敗
Idea 常用快捷鍵
快捷鍵 | 功能 |
---|---|
Alt+Enter | 導入包帚称,自動修正代碼 |
Ctrl+Y | 刪除光標所在行 |
Ctrl+D | 復制光標所在行的內(nèi)容,插入光標位置下面 |
Ctrl+Alt+L | 格式化代碼 |
Ctrl+/ | 單行注釋 |
Ctrl+Shift+/ | 選中代碼注釋秽澳,多行注釋闯睹,再按取消注釋 |
Alt+Ins | 自動生成代碼,toString担神,get楼吃,set等方法 |
Alt+Shift+上下箭頭 | 移動當前代碼行 |
數(shù)組
-
定義數(shù)組的三種方式
int[] arr = new int[3]; int[] arr = new int[]{1,2,3,4,5}; int[] arr = {1,2,3,4,5};
數(shù)組的長度屬性
arr.length
類和對象
數(shù)據(jù)類型 | 默認值 | |
---|---|---|
基本類型 | 整數(shù)(byte,short妄讯,int孩锡,long) | 0 |
浮點數(shù)(float,double) | 0.0 | |
字符(char) | '\u0000' | |
布爾(boolean) | false | |
引用類型 | 數(shù)組亥贸,類躬窜,接口 | null |
常用API
-
Scanner類
import java.util.Scanner; public class Demo01_Scanner { public static void main(String[] args) { //2. 創(chuàng)建鍵盤錄入數(shù)據(jù)的對象 Scanner sc = new Scanner(System.in); //3. 接收數(shù)據(jù) System.out.println("請錄入一個整數(shù):"); int i = sc.nextInt(); //4. 輸出數(shù)據(jù) System.out.println("i:"+i); } }
-
匿名對象
創(chuàng)建對象時,只有創(chuàng)建對象的語句炕置,卻沒有把對象地址值賦值給某個變量荣挨。雖然是創(chuàng)建對象的簡化寫法,但是應用 場景非常有限朴摊。
匿名對象 :沒有變量名的對象默垄。
一旦調(diào)用兩次方法,就是創(chuàng)建了兩個對象甚纲,造成浪費口锭。一般可作為方法的參數(shù)和返回值
new Scanner(System.in).nextInt(); new Scanner(System.in).nextInt();
-
Random類
public int nextInt(int n)
:返回一個偽隨機數(shù),范圍在 0 (包括)和 指定值 n (不包括)之間的 int 值介杆。//1. 導包 import java.util.Random; public class Demo01_Random { public static void main(String[] args) { //2. 創(chuàng)建鍵盤錄入數(shù)據(jù)的對象 Random r = new Random(); for(int i = 0; i < 3; i++){ //3. 隨機生成一個數(shù)據(jù) int number = r.nextInt(10); //4. 輸出數(shù)據(jù) System.out.println("number:"+ number); } } }
-
ArrayList類
java.util.ArrayList 是大小可變的數(shù)組的實現(xiàn)鹃操,存儲在內(nèi)的數(shù)據(jù)稱為元素韭寸。此類提供一些方法來操作內(nèi)部存儲 的元素。 ArrayList 中可不斷添加元素组民,其大小也自動增長棒仍。
public class Test02StudentArrayList { public static void main(String[] args) { //創(chuàng)建學生數(shù)組 ArrayList<String> list = new ArrayList<>(); //創(chuàng)建學生對象 String s1 = "曹操"; String s2 = "劉備"; String s3 = "孫權(quán)"; //打印學生ArrayList集合 System.out.println(list); //把學生對象作為元素添加到集合 list.add(s1); list.add(s2); list.add(s3); //打印學生ArrayList集合 System.out.println(list); } }
常用方法:
public boolean add(E e)
:將指定的元素添加到此集合的尾部。public E remove(int index)
:移除此集合中指定位置上的元素臭胜。返回被刪除的元素莫其。public E get(int index)
:返回此集合中指定位置上的元素。返回獲取的元素耸三。public int size()
:返回此集合中的元素數(shù)乱陡。遍歷集合時,可以控制索引范圍仪壮,防止越界憨颠。 String類
1.構(gòu)造方法
public String()
:初始化新創(chuàng)建的 String對象,以使其表示空字符序列积锅。
public String(char[] value)
:通過當前參數(shù)中的字符數(shù)組來構(gòu)造新的String爽彤。
public String(byte[] bytes)
:通過使用平臺的默認字符集解碼當前參數(shù)中的字節(jié)數(shù)組來構(gòu)造新的String。
2.常用方法
判斷功能:
public boolean equals (Object anObject)
:將此字符串與指定對象進行比較缚陷。
public boolean equalsIgnoreCase (String anotherString)
:將此字符串與指定對象進行比較适篙,忽略大小寫。
獲取功能:
public int length ()
:返回此字符串的長度箫爷。
public String concat (String str)
:將指定的字符串連接到該字符串的末尾嚷节。
public char charAt (int index)
:返回指定索引處的 char值。
public int indexOf (String str)
:返回指定子字符串第一次出現(xiàn)在該字符串內(nèi)的索引虎锚。
public String substring (int beginIndex)
:返回一個子字符串硫痰,從beginIndex開始截取字符串到字符串結(jié)尾。
public String substring (int beginIndex, int endIndex)
:返回一個子字符串窜护,從beginIndex到endIndex截取字符串效斑。含beginIndex,不含endIndex柄慰。
轉(zhuǎn)換功能:
public char[] toCharArray ()
:將此字符串轉(zhuǎn)換為新的字符數(shù)組鳍悠。
public byte[] getBytes ()
:使用平臺的默認字符集將該 String編碼轉(zhuǎn)換為新的字節(jié)數(shù)組。
public String replace (CharSequence target, CharSequence replacement)
:將與target匹配的字符串使用replacement字符串替換坐搔。
分割功能:
public String[] split(String regex)
:將此字符串按照給定的regex(規(guī)則)拆分為字符串數(shù)組藏研。
public class String_Demo03 {
public static void main(String[] args) {
//創(chuàng)建字符串對象
String s = "aa|bb|cc";
String[] strArray = s.split("|"); // ["aa","bb","cc"]
for(int x = 0; x < strArray.length; x++) {
System.out.println(strArray[x]); // aa bb cc
}
}
}
- static 關(guān)鍵字
關(guān)于 static 關(guān)鍵字的使用,它可以用來修飾的成員變量和成員方法概行,被修飾的成員是屬于類的蠢挡,而不是單單是屬于某個對象的。也就是說,既然屬于類业踏,就可以不靠創(chuàng)建對象來調(diào)用了禽炬。
1.類變量:使用 static關(guān)鍵字修飾的成員變量。
static 數(shù)據(jù)類型 變量名勤家;
static int numberID腹尖;
2.類方法:即靜態(tài)方法
當 static 修飾成員方法時,該方法稱為類方法 伐脖。靜態(tài)方法在聲明中有 static 热幔,建議使用類名來調(diào)用,而不需要創(chuàng)建類的對象讼庇。
靜態(tài)方法調(diào)用的注意事項:
靜態(tài)方法可以直接訪問類變量和靜態(tài)方法绎巨。
靜態(tài)方法不能直接訪問普通成員變量或成員方法。反之蠕啄,成員方法可以直接訪問類變量或靜態(tài)方法场勤。
靜態(tài)方法中,不能使用this關(guān)鍵字歼跟。
3.靜態(tài)代碼塊
靜態(tài)代碼塊:定義在成員位置和媳,使用static修飾的代碼塊{ }。
位置:類中方法外哈街。
執(zhí)行:隨著類的加載而執(zhí)行且執(zhí)行一次窗价,優(yōu)先于main方法和構(gòu)造方法的執(zhí)行。
格式:
public class ClassName{
static {
// 執(zhí)行語句
}
}
static 關(guān)鍵字叹卷,可以修飾變量、方法和代碼塊坪它。在使用的過程中骤竹,其主要目的還是想在不創(chuàng)建對象的情況下,去調(diào)用方法往毡。
Object類
public String toString()
:返回該對象的字符串表示蒙揣。
public boolean equals(Object obj)
:指示其他某個對象是否與此對象“相等”。Objects類
在JDK7添加了一個Objects工具類开瞭,它提供了一些方法來操作對象懒震,它由一些靜態(tài)的實用方法組成,這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的)嗤详,用于計算對象的hashcode个扰、返回對象的字符串表示形式、比較兩個對象葱色。
在比較兩個對象的時候递宅,Object的equals方法容易拋出空指針異常,而Objects類中的equals方法就優(yōu)化了這個問題。方法如下:
public static boolean equals(Object a, Object b)
:判斷兩個對象是否相等办龄。
我們可以查看一下源碼烘绽,學習一下:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
- Date類
public Date()
:分配Date對象并初始化此對象,以表示分配它的時間(精確到毫秒)俐填。
public Date(long date)
:分配Date對象并初始化此對象安接,以表示自從標準基準時間(稱為“歷元(epoch)”,即1970年1月1日00:00:00 GMT)以來的指定毫秒數(shù)英融。
import java.util.Date;
public class Demo01Date {
public static void main(String[] args) {
// 創(chuàng)建日期對象盏檐,把當前的時間
System.out.println(new Date()); // Tue Jan 16 14:37:35 CST 2018
// 創(chuàng)建日期對象,把當前的毫秒值轉(zhuǎn)成日期對象
System.out.println(new Date(0L)); // Thu Jan 01 08:00:00 CST 1970
}
}
tips:在使用println方法時矢赁,會自動調(diào)用Date類中的toString方法糯笙。Date類對Object類中的toString方法進行了覆蓋重寫,所以結(jié)果為指定格式的字符串撩银。
public long getTime()
把日期對象轉(zhuǎn)換成對應的時間毫秒值给涕。
- DateFormat類
格式化:按照指定的格式,從Date對象轉(zhuǎn)換為String對象额获。
解析:按照指定的格式够庙,從String對象轉(zhuǎn)換為Date對象。
由于DateFormat為抽象類抄邀,不能直接使用耘眨,所以需要常用的子類java.text.SimpleDateFormat
。這個類需要一個模式(格式)來指定格式化或解析的標準境肾。構(gòu)造方法為:
-
public SimpleDateFormat(String pattern)
:用給定的模式和默認語言環(huán)境的日期格式符號構(gòu)造SimpleDateFormat剔难。參數(shù)pattern是一個字符串,代表日期時間的自定義格式奥喻。
常用的格式規(guī)則為:
標識字母(區(qū)分大小寫) | 含義 |
---|---|
y | 年 |
M | 月 |
d | 日 |
H | 時 |
m | 分 |
s | 秒 |
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class Demo02SimpleDateFormat {
public static void main(String[] args) {
// 對應的日期格式如:2018-01-16 15:06:38
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
}
DateFormat類的常用方法有:
public String format(Date date)
:將Date對象格式化為字符串偶宫。
public Date parse(String source)
:將字符串解析為Date對象。
- System類
java.lang.System
類中提供了大量的靜態(tài)方法环鲤,可以獲取與系統(tǒng)相關(guān)的信息或系統(tǒng)級操作纯趋,在System類的API文檔中,常用的方法有:
public static long currentTimeMillis()
:返回以毫秒為單位的當前時間冷离。
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
:將數(shù)組中指定的數(shù)據(jù)拷貝到另一個數(shù)組中吵冒。
實際上,currentTimeMillis方法就是 獲取當前系統(tǒng)時間與1970年01月01日00:00點之間的毫秒差值
import java.util.Date;
public class SystemDemo {
public static void main(String[] args) {
//獲取當前時間毫秒值
System.out.println(System.currentTimeMillis()); // 1516090531144
}
}
將src數(shù)組中前3個元素西剥,復制到dest數(shù)組的前3個位置上復制元素前:src數(shù)組元素[1,2,3,4,5]痹栖,dest數(shù)組元素[6,7,8,9,10]復制元素后:src數(shù)組元素[1,2,3,4,5],dest數(shù)組元素[1,2,3,9,10]
import java.util.Arrays;
public class Demo11SystemArrayCopy {
public static void main(String[] args) {
int[] src = new int[]{1,2,3,4,5};
int[] dest = new int[]{6,7,8,9,10};
System.arraycopy( src, 0, dest, 0, 3);
/*代碼運行后:兩個數(shù)組中的元素發(fā)生了變化
src數(shù)組元素[1,2,3,4,5]
dest數(shù)組元素[1,2,3,9,10]
*/
}
}
- StringBuilder類
StringBuilder是個字符串的緩沖區(qū)蔫耽,即它是一個容器结耀,容器中可以裝很多字符串留夜。并且能夠?qū)ζ渲械淖址M行各種操作。
根據(jù)StringBuilder的API文檔图甜,常用構(gòu)造方法有2個:
public StringBuilder()
:構(gòu)造一個空的StringBuilder容器碍粥。
public StringBuilder(String str)
:構(gòu)造一個StringBuilder容器,并將字符串添加進去黑毅。
StringBuilder常用的方法有2個:
public StringBuilder append(...)
:添加任意類型數(shù)據(jù)的字符串形式嚼摩,并返回當前對象自身。
public String toString()
:將當前StringBuilder對象轉(zhuǎn)換為String對象矿瘦。
append方法具有多種重載形式枕面,可以接收任意類型的參數(shù)。任何數(shù)據(jù)作為參數(shù)都會將對應的字符串內(nèi)容添加到StringBuilder中缚去。例如:
public class Demo02StringBuilder {
public static void main(String[] args) {
//創(chuàng)建對象
StringBuilder builder = new StringBuilder();
//public StringBuilder append(任意類型)
StringBuilder builder2 = builder.append("hello");
//對比一下
System.out.println("builder:"+builder);
System.out.println("builder2:"+builder2);
System.out.println(builder == builder2); //true
// 可以添加 任何類型
builder.append("hello");
builder.append("world");
builder.append(true);
builder.append(100);
// 在我們開發(fā)中潮秘,會遇到調(diào)用一個方法后,返回一個對象的情況易结。然后使用返回的對象繼續(xù)調(diào)用方法枕荞。
// 這種時候,我們就可以把代碼現(xiàn)在一起搞动,如append方法一樣躏精,代碼如下
//鏈式編程
builder.append("hello").append("world").append(true).append(100);
System.out.println("builder:"+builder);
}
}
備注:StringBuilder已經(jīng)覆蓋重寫了Object當中的toString方法。
通過toString方法鹦肿,StringBuilder對象將會轉(zhuǎn)換為不可變的String對象矗烛。如:
public class Demo16StringBuilder {
public static void main(String[] args) {
// 鏈式創(chuàng)建
StringBuilder sb = new StringBuilder("Hello").append("World").append("Java");
// 調(diào)用方法
String str = sb.toString();
System.out.println(str); // HelloWorldJava
}
}
- 包裝類
基本數(shù)值---->包裝對象
Integer i = new Integer(4);//使用構(gòu)造函數(shù)函數(shù)
Integer iii = Integer.valueOf(4);//使用包裝類中的valueOf方法
包裝對象---->基本數(shù)值
int num = i.intValue();
由于我們經(jīng)常要做基本類型與包裝類之間的轉(zhuǎn)換,從Java 5(JDK 1.5)開始箩溃,基本類型與包裝類的裝箱瞭吃、拆箱動作可以自動完成。例如:
Integer i = 4;//自動裝箱涣旨。相當于Integer i = Integer.valueOf(4);
i = i + 5;//等號右邊:將i對象轉(zhuǎn)成基本數(shù)值(自動拆箱) i.intValue() + 5;
//加法運算完成后虱而,再次裝箱,把基本數(shù)值轉(zhuǎn)成對象开泽。
基本類型與字符串之間的轉(zhuǎn)換:
基本類型直接與””相連接即可;如:34+""
String轉(zhuǎn)換成對應的基本類型
除了Character類之外魁瞪,其他所有包裝類都具有parseXxx靜態(tài)方法可以將字符串參數(shù)轉(zhuǎn)換為對應的基本類型:
public static byte parseByte(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的byte基本類型穆律。
public static short parseShort(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的short基本類型。
public static int parseInt(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的int基本類型导俘。
public static long parseLong(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的long基本類型峦耘。
public static float parseFloat(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的float基本類型。
public static double parseDouble(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的double基本類型旅薄。
public static boolean parseBoolean(String s)
:將字符串參數(shù)轉(zhuǎn)換為對應的boolean基本類型辅髓。
繼承
- 格式
class 父類 {
...
}
class 子類 extends 父類 {
...
}
-
成員變量
1.如果子類父類中出現(xiàn)不重名的成員變量泣崩,這時的訪問是沒有影響的。
2.如果子類父類中出現(xiàn)重名的成員變量洛口,這時的訪問是有影響的矫付。
子父類中出現(xiàn)了同名的成員變量時,在子類中需要訪問父類中非私有成員變量時第焰,需要使用 super 關(guān)鍵字买优,修飾父類成員變量,類似于之前學過的 this 挺举。
class Fu {
// Fu中的成員變量杀赢。
int num = 5;
}
class Zi extends Fu {
// Zi中的成員變量
int num = 6;
public void show() {
// 訪問父類中的num
System.out.println("Fu num=" + super.num);
// 訪問子類中的num
System.out.println("Zi num=" + this.num);
}
}
class ExtendsDemo03 {
public static void main(String[] args) {
// 創(chuàng)建子類對象
Zi z = new Zi();
// 調(diào)用子類中的show方法
z.show();
}
}
演示結(jié)果:
Fu num = 5
Zi num = 6
小貼士:Fu 類中的成員變量是非私有的,子類中可以直接訪問湘纵。若Fu 類中的成員變量私有了脂崔,子類是不能直接訪問的。通常編碼時梧喷,我們遵循封裝的原則砌左,使用private修飾成員變量,那么如何訪問父類的私有成員變量呢伤柄?對绊困!可以在父類中提供公共的getXxx方法和setXxx方法。
-
成員方法
1.如果子類父類中出現(xiàn)不重名的成員方法,這時的調(diào)用是沒有影響的。對象調(diào)用方法時操漠,會先在子類中查找有沒有對應的方法毯焕,若子類中存在就會執(zhí)行子類中的方法,若子類中不存在就會執(zhí)行父類中相應的方法糠惫。
2.如果子類父類中出現(xiàn)重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override)作谭。
小貼士:重寫時,用到super.父類成員方法奄毡,表示調(diào)用父類的成員方法
注意事項
子類方法覆蓋父類方法折欠,必須要保證權(quán)限大于等于父類權(quán)限。
子類方法覆蓋父類方法吼过,返回值類型锐秦、函數(shù)名和參數(shù)列表都要一模一樣。
- *構(gòu)造方法
- 構(gòu)造方法的名字是與類名一致的盗忱。所以子類是無法繼承父類構(gòu)造方法的酱床。
- 構(gòu)造方法的作用是初始化成員變量的。所以子類的初始化過程中趟佃,必須先執(zhí)行父類的初始化動作扇谣。子類的構(gòu)造方法中默認有一個 super() 昧捷,表示調(diào)用父類的構(gòu)造方法,父類成員變量初始化后罐寨,才可以給子類使用靡挥。
this(...) ‐‐ 本類的構(gòu)造方法
super(...) ‐‐ 父類的構(gòu)造方法
子類的每個構(gòu)造方法中均有默認的super(),調(diào)用父類的空參構(gòu)造衩茸。手動調(diào)用父類構(gòu)造會覆蓋默認的super()芹血。super() 和 this() 都必須是在構(gòu)造方法的第一行,所以不能同時出現(xiàn)楞慈。
抽象類
定義:
抽象方法 : 沒有方法體的方法幔烛。
抽象類:包含抽象方法的類。
-
抽象方法
使用 abstract 關(guān)鍵字修飾方法囊蓝,該方法就成了抽象方法饿悬,抽象方法只包含一個方法名,而沒有方法體聚霜。
修飾符 abstract 返回值類型 方法名 (參數(shù)列表)狡恬;
public abstract void run();
-
抽象類
如果一個類包含抽象方法蝎宇,那么該類必須是抽象類弟劲。
abstract class 類名字 {
}
public abstract class Animal {
public abstract void run();
}
繼承抽象類的子類必須重寫父類所有的抽象方法姥芥。否則兔乞,該子類也必須聲明為抽象類。最終凉唐,必須有子類實現(xiàn)該父類的抽象方法庸追,否則,從最初的父類到最終的子類都不能創(chuàng)建對象台囱,失去意義淡溯。
注意事項
- 抽象類不能創(chuàng)建對象,如果創(chuàng)建簿训,編譯無法通過而報錯咱娶。只能創(chuàng)建其非抽象子類的對象。
理解:假設創(chuàng)建了抽象類的對象强品,調(diào)用抽象的方法豺总,而抽象方法沒有具體的方法體,沒有意義择懂。- 抽象類中,可以有構(gòu)造方法另玖,是供子類創(chuàng)建對象時困曙,初始化父類成員使用的表伦。
理解:子類的構(gòu)造方法中,有默認的super()慷丽,需要訪問父類構(gòu)造方法蹦哼。- 抽象類中,不一定包含抽象方法要糊,但是有抽象方法的類必定是抽象類
理解:未包含抽象方法的抽象類纲熏,目的就是不想讓調(diào)用者創(chuàng)建該類對象,通常用于某些特殊的類結(jié)構(gòu)設計锄俄。- 抽象類的子類局劲,必須重寫抽象父類中所有的抽象方法,否則奶赠,編譯無法通過而報錯鱼填。除非該子類也是抽象類。
理解:假設不重寫所有抽象方法毅戈,則類中可能包含抽象方法苹丸。那么創(chuàng)建對象后,調(diào)用抽象的方法苇经,沒有意義赘理。
接口
接口,是Java語言中一種引用類型扇单,是方法的集合商模,如果說類的內(nèi)部封裝了成員變量、構(gòu)造方法和成員方法令花,那么接口的內(nèi)部主要就是封裝了方法阻桅,包含抽象方法(JDK 7及以前),默認方法和靜態(tài)方法(JDK 8)兼都,私有方法(JDK 9)嫂沉。
接口的定義,它與定義類方式相似扮碧,但是使用 interface 關(guān)鍵字趟章。它也會被編譯成.class文件,但一定要明確它并不是類慎王,而是另外一種引用數(shù)據(jù)類型蚓土。引用數(shù)據(jù)類型:數(shù)組,類赖淤,接口蜀漆。
接口的使用,它不能創(chuàng)建對象咱旱,但是可以被實現(xiàn)( implements 确丢,類似于被繼承)绷耍。一個實現(xiàn)接口的類(可以看做是接口的子類),需要實現(xiàn)接口中所有的抽象方法鲜侥,創(chuàng)建該類對象褂始,就可以調(diào)用方法了,否則它必須是一個抽象類描函。
定義格式
public interface 接口名稱 {
// 抽象方法
// 默認方法
// 靜態(tài)方法
// 私有方法
}
/*
含有抽象方法
抽象方法:使用 abstract 關(guān)鍵字修飾崎苗,可以省略,沒有方法體舀寓。該方法供子類實現(xiàn)使用胆数。
*/
public interface InterFaceName {
public abstract void method(); //使用 abstract 關(guān)鍵字修飾,可以省略基公,沒有方法體幅慌。
}
/*
含有默認方法和靜態(tài)方法
默認方法:使用 default 修飾,不可省略轰豆,供子類調(diào)用或者子類重寫胰伍。
靜態(tài)方法:使用 static 修飾,供接口直接調(diào)用酸休。靜態(tài)與.class 文件相關(guān)骂租,只能使用接口名調(diào)用,不可以通過實現(xiàn)類的類名或者實現(xiàn)類的對象調(diào)用
*/
public interface InterFaceName {
public default void method() {
// 執(zhí)行語句
}
public static void method2() {
// 執(zhí)行語句
}
}
/*含有私有方法和私有靜態(tài)方法
私有方法:使用 private 修飾斑司,供接口中的默認方法或者靜態(tài)方法調(diào)用渗饮。*/
public interface InterFaceName {
private void method() {
// 執(zhí)行語句
}
}
- 基本實現(xiàn)
類與接口的關(guān)系為實現(xiàn)關(guān)系,即類實現(xiàn)接口宿刮,該類可以稱為接口的實現(xiàn)類互站,也可以稱為接口的子類。實現(xiàn)的動作類似繼承僵缺,格式相仿胡桃,只是關(guān)鍵字不同,實現(xiàn)使用 implements 關(guān)鍵字磕潮。
非抽象子類實現(xiàn)接口:
- 必須重寫接口中所有抽象方法翠胰。
- 繼承了接口的默認方法,即可以直接調(diào)用自脯,也可以重寫之景。但是只能通過實現(xiàn)類的對象來調(diào)用
實現(xiàn)格式:
class 類名 implements 接口名 {
// 重寫接口中抽象方法【必須】
// 重寫接口中默認方法【可選】
}
Tips:
類的靜態(tài)變量和靜態(tài)方法能否被子類繼承?
結(jié)論:java中靜態(tài)屬性和靜態(tài)方法可以被繼承膏潮,但是沒有被重寫(overwrite)而是被隱藏.
原因:
1). 靜態(tài)方法和屬性是屬于類的锻狗,調(diào)用的時候直接通過類名.方法名完成對,不需要繼承機制及可以調(diào)用。如果子類里面定義了靜態(tài)方法和屬性轻纪,那么這時候父類的靜態(tài)方法或?qū)傩苑Q之為"隱藏"脚囊。如果你想要調(diào)用父類的靜態(tài)方法和屬性,直接通過父類名.方法或變量名完成桐磁,至于是否繼承一說,子類是有繼承靜態(tài)方法和屬性讲岁,但是跟實例方法和屬性不太一樣我擂,存在"隱藏"的這種情況。
2). 多態(tài)之所以能夠?qū)崿F(xiàn)依賴于繼承缓艳、接口和重寫校摩、重載(繼承和重寫最為關(guān)鍵)。有了繼承和重寫就可以實現(xiàn)父類的引用指向不同子類的對象阶淘。重寫的功能是:"重寫"后子類的優(yōu)先級要高于父類的優(yōu)先級衙吩,但是“隱藏”是沒有這個優(yōu)先級之分的。
3). 靜態(tài)屬性溪窒、靜態(tài)方法和非靜態(tài)的屬性都可以被繼承和隱藏而不能被重寫坤塞,因此不能實現(xiàn)多態(tài),不能實現(xiàn)父類的引用可以指向不同子類的對象澈蚌。非靜態(tài)方法可以被繼承和重寫摹芙,因此可以實現(xiàn)多態(tài)。
package com.study.test;
public class A { //父類
public static String staticStr = "A靜態(tài)屬性";
public String nonStaticStr = "A非靜態(tài)屬性";
public static void staticMethod(){
System.out.println("A靜態(tài)方法");
}
public void nonStaticMethod(){
System.out.println("A非靜態(tài)方法");
}
}
package com.study.test;
public class B extends A{//子類B
public static String staticStr = "B改寫后的靜態(tài)屬性";
public String nonStaticStr = "B改寫后的非靜態(tài)屬性";
public static void staticMethod(){
System.out.println("B改寫后的靜態(tài)方法");
}
}
package com.study.test;
public class C extends A{//子類C繼承A中的所有屬性和方法
}
package com.study.test;
public class StaticExtendsTest {
public static void main(String[] args) {
C c = new C();
System.out.println(c.nonStaticStr);
System.out.println(c.staticStr);
c.staticMethod();//輸出的結(jié)果都是父類中的非靜態(tài)屬性宛瞄、靜態(tài)屬性和靜態(tài)方法,推出靜態(tài)屬性和靜態(tài)方法可以被繼承
System.out.println("-------------------------------");
A c1 = new C();
System.out.println(c1.nonStaticStr);
System.out.println(c1.staticStr);
c1.staticMethod();//結(jié)果同上浮禾,輸出的結(jié)果都是父類中的非靜態(tài)屬性、靜態(tài)屬性和靜態(tài)方法,推出靜態(tài)屬性和靜態(tài)方法可以被繼承
System.out.println("-------------------------------");
B b = new B();
System.out.println(b.nonStaticStr);
System.out.println(b.staticStr);
b.staticMethod();
System.out.println("-------------------------------");
A b1 = new B();
System.out.println(b1.nonStaticStr);
System.out.println(b1.staticStr);
b1.staticMethod();//結(jié)果都是父類的靜態(tài)方法份汗,說明靜態(tài)方法不可以被重寫盈电,不能實現(xiàn)多態(tài)
}
}
測試結(jié)果如下:
A非靜態(tài)屬性
A靜態(tài)屬性
A靜態(tài)方法
-------------------------------
A非靜態(tài)屬性
A靜態(tài)屬性
A靜態(tài)方法
-------------------------------
B改寫后的非靜態(tài)屬性
B改寫后的靜態(tài)屬性
B改寫后的靜態(tài)方法
-------------------------------
A非靜態(tài)屬性
A靜態(tài)屬性
A靜態(tài)方法
- 接口的多實現(xiàn)
之前學過,在繼承體系中杯活,一個類只能繼承一個父類匆帚。而對于接口而言,一個類是可以實現(xiàn)多個接口的轩猩,這叫做接口的多實現(xiàn)卷扮。并且,一個類能繼承一個父類均践,同時實現(xiàn)多個接口晤锹。
class 類名 [extends 父類名] implements 接口名1,接口名2,接口名3... {
// 重寫接口中抽象方法【必須】
// 重寫接口中默認方法【不重名時可選】
}
接口中,有多個抽象方法時彤委,實現(xiàn)類必須重寫所有抽象方法鞭铆。如果抽象方法有重名的,只需要重寫一次.
接口中,有多個默認方法時车遂,實現(xiàn)類都可繼承使用封断。如果默認方法有重名的,必須重寫一次
接口中舶担,存在同名的靜態(tài)方法并不會沖突坡疼,原因是只能通過各自接口名訪問靜態(tài)方法。
- 接口的多繼承
一個接口能繼承另一個或者多個接口衣陶,這和類之間的繼承比較相似柄瑰。接口的繼承使用 extends 關(guān)鍵字,子接口繼承父接口的方法剪况。如果父接口中的默認方法有重名的教沾,那么子接口需要重寫一次。
小貼士:
子接口重寫默認方法時译断,default關(guān)鍵字可以保留授翻。
子類重寫默認方法時,default關(guān)鍵字不可以保留孙咪。
接口中堪唐,無法定義成員變量,但是可以定義常量该贾,其值不可以改變羔杨,默認使用public static final修飾。
接口中杨蛋,沒有構(gòu)造方法兜材,不能創(chuàng)建對象。
接口中逞力,沒有靜態(tài)代碼塊曙寡。
多態(tài)
多態(tài)是繼封裝、繼承之后寇荧,面向?qū)ο蟮牡谌筇匦?/p>
父類類型 變量名 = new 子類對象举庶;
變量名.方法名();
Fu f = new Zi();
f.method(); //多態(tài)規(guī)定,執(zhí)行的是子類重寫的方法
- 多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型與向下轉(zhuǎn)型兩種:
向上轉(zhuǎn)型
向上轉(zhuǎn)型:多態(tài)本身是子類類型向父類類型向上轉(zhuǎn)換的過程揩抡,這個過程是默認的户侥。
當父類引用指向一個子類對象時,便是向上轉(zhuǎn)型峦嗤。
使用格式:
父類類型 變量名 = new 子類類型();
如:Animal a = new Cat();
向下轉(zhuǎn)型
向下轉(zhuǎn)型:父類類型向子類類型向下轉(zhuǎn)換的過程蕊唐,這個過程是強制的。
使用格式:
子類類型 變量名 = (子類類型) 父類變量名;
如:Cat c =(Cat) a;
當使用多態(tài)方式調(diào)用方法時烁设,首先檢查父類中是否有該方法替梨,如果沒有,則編譯錯誤。也就是說副瀑,不能調(diào)用子類擁有弓熏,而父類沒有的方法。編譯都錯誤糠睡,更別說運行了挽鞠。這也是多態(tài)給我們帶來的一點"小麻煩"。所以狈孔,想要調(diào)用子類特有的方法滞谢,必須做向下轉(zhuǎn)型。
轉(zhuǎn)型的異常
轉(zhuǎn)型的過程中除抛,一不小心就會遇到這樣的問題,請看如下代碼:
public class Test {
public static void main(String[] args) {
// 向上轉(zhuǎn)型
Animal a = new Cat();
a.eat(); // 調(diào)用的是 Cat 的 eat
// 向下轉(zhuǎn)型
Dog d = (Dog)a;
d.watchHouse(); // 調(diào)用的是 Dog 的 watchHouse 【運行報錯】
}
}
為了避免ClassCastException的發(fā)生母截,Java提供了 instanceof 關(guān)鍵字到忽,給引用變量做類型的校驗,格式如下:
變量名 instanceof 數(shù)據(jù)類型
如果變量屬于該數(shù)據(jù)類型清寇,返回true喘漏。
如果變量不屬于該數(shù)據(jù)類型,返回false华烟。
public class Test {
public static void main(String[] args) {
// 向上轉(zhuǎn)型
Animal a = new Cat();
a.eat(); // 調(diào)用的是 Cat 的 eat
// 向下轉(zhuǎn)型
if (a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse(); // 調(diào)用的是 Cat 的 catchMouse
} else if (a instanceof Dog){
Dog d = (Dog)a;
d.watchHouse(); // 調(diào)用的是 Dog 的 watchHouse
}
}
}
final關(guān)鍵字
final: 不可改變翩迈。可以用于修飾類盔夜、方法和變量负饲。
類:被修飾的類,不能被繼承喂链。
方法:被修飾的方法返十,不能被重寫。
變量:被修飾的變量椭微,不能被重新賦值洞坑。
- 修飾類
查詢API發(fā)現(xiàn)像 public final class String 、 public final class Math 蝇率、 public final class Scanner等迟杂,很多我們學習過的類,都是被final修飾的本慕,目的就是供我們使用排拷,而不讓我們所以改變其內(nèi)容。 - 修飾方法
修飾符 final 返回值類型 方法名(參數(shù)列表){
//方法體
}
重寫被 final 修飾的方法间狂,編譯時就會報錯攻泼。
- 修飾變量
1、局部變量——基本類型
基本類型的局部變量,被final修飾后忙菠,只能賦值一次何鸡,不能再更改。
public class FinalDemo1 {
public static void main(String[] args) {
// 聲明變量牛欢,使用final修飾
final int a;
// 第一次賦值
a = 10;
// 第二次賦值
a = 20; // 報錯,不可重新賦值
// 聲明變量骡男,直接賦值,使用final修飾
final int b = 10;
// 第二次賦值
b = 20; // 報錯,不可重新賦值
}
}
- 局部變量——引用類型
引用類型的局部變量傍睹,被final修飾后隔盛,只能指向一個對象,地址不能再更改拾稳。但是不影響對象內(nèi)部的成員變量值的修改
public class FinalDemo2 {
public static void main(String[] args) {
// 創(chuàng)建 User 對象
final User u = new User();
// 創(chuàng)建 另一個 User對象
u = new User(); // 報錯吮炕,指向了新的對象,地址值改變访得。
// 調(diào)用setName方法
u.setName("張三"); // 可以修改
}
}
- 成員變量
成員變量涉及到初始化的問題龙亲,初始化方式有兩種,只能二選一
被final修飾的常量名稱悍抑,一般都有書寫規(guī)范鳄炉,所有字母都大寫。
顯示初始化:
public class User {
final String USERNAME = "張三";
private int age;
}
構(gòu)造方法初始化:
public class User {
final String USERNAME ;
private int age;
public User(String username, int age) {
this.USERNAME = username;
this.age = age;
}
}
權(quán)限修飾符
public | protected | default(空的) | private | |
---|---|---|---|---|
同一類中 | √ | √ | √ | |
同一包中(子類與無關(guān)類) | √ | √ | √ | |
不同包的子類 | √ | √ | ||
不同包中的無關(guān)類 | √ |
編寫代碼時搜骡,如果沒有特殊的考慮拂盯,建議這樣使用權(quán)限:
成員變量使用 private ,隱藏細節(jié)记靡。
構(gòu)造方法使用 public 谈竿,方便創(chuàng)建對象。
成員方法使用 public 摸吠,方便調(diào)用方法榕订。
小貼士:不加權(quán)限修飾符,其訪問能力與default修飾符相同
內(nèi)部類
成員內(nèi)部類
成員內(nèi)部類 :定義在類中方法外的類蜕便。
class 外部類 {
class 內(nèi)部類{
}
}
訪問特點
內(nèi)部類可以直接訪問外部類的成員劫恒,包括私有成員。
外部類要訪問內(nèi)部類的成員轿腺,必須要建立內(nèi)部類的對象两嘴。
創(chuàng)建內(nèi)部類對象格式:
外部類名.內(nèi)部類名 對象名 = new 外部類型().new 內(nèi)部類型();
public class Person {
private boolean live = true;
class Heart {
public void jump() {
// 直接訪問外部類成員
if (live) {
System.out.println("心臟在跳動");
} else {
System.out.println("心臟不跳了");
}
}
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
}
public class InnerDemo {
public static void main(String[] args) {
// 創(chuàng)建外部類對象
Person p = new Person();
// 創(chuàng)建內(nèi)部類對象
Heart heart = p.new Heart();
// 調(diào)用內(nèi)部類方法
heart.jump();
// 調(diào)用外部類方法
p.setLive(false);
// 調(diào)用內(nèi)部類方法
heart.jump();
}
}
輸出結(jié)果:
心臟在跳動
心臟不跳了
-
匿名內(nèi)部類對象
匿名內(nèi)部類 :是內(nèi)部類的簡化寫法族壳。它的本質(zhì)是一個 帶具體實現(xiàn)的 父類或者父接口的 匿名的 子類對象憔辫。
格式:
new 父類名或者接口名(){
// 方法重寫
@Override
public void method() {
// 執(zhí)行語句
}
};
public abstract class FlyAble{
public abstract void fly();
}
public class InnerDemo {
public static void main(String[] args) {
/*
1.等號右邊:是匿名內(nèi)部類,定義并創(chuàng)建該接口的子類對象
2.等號左邊:是多態(tài)賦值,接口類型引用指向子類對象
*/
FlyAble f = new FlyAble(){
public void fly() {
System.out.println("我飛了~~~");
}
};
//調(diào)用 fly方法,執(zhí)行重寫后的方法
f.fly();
}
}