Java的一些特性
變數
java的變數相對於c語言而言不能重複定義會爆錯
int e,f = 30;
上述的程式碼相當於f為30,e沒有進行復制
強型別語言:每個變數都必須宣告其型別
資料型別
資料型別分為:1、基本資料型別:數值型(整數型別(byte、short、int、long)浮點型別(float、double))、字元型(char)、布林型(boolean)
2、引用資料型別:類(class)、介面(interface)、陣列。
在 Java 中,輸出可以以多種形式進行,但最終都是透過字元流或位元組流的方式輸出到控制檯、檔案或其他輸出裝置。以下是一些常見的輸出方式及其特點:
在輸出的時候+先執行加法操作則之後如果是數與數的操作則還是加法操作
如果先是連線操作則下面還是連線操作:
System.out.println("輸出的是"+now);
System.out.println("結果為"+5+6);
在輸出超過int型別的整數的時候則要在數值的最後新增L
long a = 1234567899L;
字串使用float的時候則要在字串的最後新增f:
float now = 3.14f;
方法(函式)
與c++的區別:
-
C++ 函式:
- 函式是獨立的程式碼塊,可以在全域性範圍內定義,也可以定義在類內部(稱為成員函式)。
- C++ 支援全域性函式和名稱空間中的函式。
-
Java 方法:
-
方法是類的一部分,必須在類內部定義。Java 不支援全域性函式。
-
方法是物件的行為,通常與物件的狀態(屬性)相關聯。
-
C++ 支援函式過載(同名函式引數不同)和虛擬函式(支援多型,透過基類指標或引用呼叫派生類的方法)。
-
C++ 中的虛擬函式透過
virtual
關鍵字宣告,允許在派生類中重寫。 -
Java 也支援方法過載和方法重寫。重寫的方法必須與父類中的方法具有相同的名稱和引數列表。
-
在 Java 中,所有的方法預設都是虛擬的,除非使用
final
或static
關鍵字修飾。
-
在 Java 中,函式引數不能有預設值,因此你提供的這個程式碼片段是無效的。Java 不支援像 C++ 那樣在方法引數中指定預設值。
java方法的過載:在同一類中的方法名相同,形參列表不同的多個方法構成方法的過載,其中的形參列表可以是型別不同、順序不同、個數不同
陣列
在 Java 中,陣列的定義和初始化是兩個不同的概念,它們的順序和方式與 Java 的記憶體管理和虛擬機器(JVM)的工作機制有關。下面是對這一現象的詳細解釋:
1. 陣列的定義與初始化
-
定義:在 Java 中,定義陣列是指宣告一個陣列變數,指定其型別和名稱,但並不分配記憶體。
int[] myArray; // 定義一個整型陣列變數
-
初始化:初始化陣列是指分配記憶體並設定陣列的初始值。可以透過以下方式進行初始化:
myArray = new int[10]; // 初始化陣列,分配記憶體空間
或者結合定義和初始化:
int[] myArray = new int[10]; // 定義並初始化陣列
2. 虛擬機器與記憶體管理
- 記憶體分配:在 Java 中,陣列的記憶體分配是由 JVM 管理的。當你使用
new
關鍵字初始化陣列時,JVM 會在堆記憶體中分配相應的空間。JVM 負責管理記憶體的分配和釋放,這與虛擬機器的設計有關。 - 型別安全:Java 是一種強型別語言,因此在定義陣列時需要指定陣列的型別。這是為了確保在使用陣列時能夠進行型別檢查,避免型別不匹配的錯誤。
3. 為什麼需要先定義再初始化
- 清晰的語義:透過先定義陣列,程式設計師可以清楚地知道該變數的型別和用途。這有助於程式碼的可讀性和可維護性。
- 避免空指標異常:在 Java 中,未初始化的陣列變數預設值為
null
。在使用陣列之前必須先初始化它,這樣可以減少空指標異常的風險。 - 記憶體管理:透過分開定義和初始化,可以更靈活地管理記憶體。例如,你可以在條件語句中根據需要來初始化陣列。
4. 總結
陣列在 Java 中需要先定義再初始化的原因與 Java 的記憶體管理、型別安全以及程式碼的可讀性等因素有關。這並不是因為虛擬化的緣故,而是 Java 語言設計的基本原則和 JVM 的記憶體管理機制共同導致的。透過這種方式,Java 提供了更安全和更清晰的程式設計體驗。
陣列的增強輸出:
int[] arr;
arr = new int[4];
int[] now = new int[66];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
System.out.println("陣列的檢視:增強for迴圈方式:");
for(int num:arr){//對arr陣列進行遍歷,遍歷出來的每一個元素用num進行接收
System.out.println(num);
}
增強for迴圈和正常for迴圈的區別:
1. 用途
- 增強
for
迴圈:- 主要用於遍歷集合或陣列,簡化了程式碼,避免了顯式的索引操作。
- 適合於只需要讀取元素的場景,不適合於需要修改元素的情況。
- 正常
for
迴圈:- 更靈活,可以自由控制迴圈的起始位置、終止條件和步進值。
- 適合於需要修改元素、訪問特定索引或需要複雜邏輯的場景。
2. 可讀性
- 增強
for
迴圈:- 更加簡潔和易讀,特別是在處理集合時,程式碼更清晰。
- 減少了錯誤的可能性,如索引越界等。
- 正常
for
迴圈:- 程式碼相對較長,可能會增加出錯的機會,尤其是在複雜的迴圈條件下。
3. 效能
- 增強
for
迴圈:- 在大多數情況下,效能與正常
for
迴圈相似,因為它在內部仍然使用迭代器或索引。 - 但在某些情況下,增強
for
迴圈可能會略微影響效能,特別是在處理大型資料集時。
- 在大多數情況下,效能與正常
- 正常
for
迴圈:- 由於可以直接使用索引訪問陣列元素,可能在某些情況下表現得更高效,尤其是在陣列操作中。
總結
-
增強
for
迴圈 更加簡潔和易讀,適合用於遍歷集合或陣列,但不適合需要修改元素或複雜邏輯的情況。 -
正常
for
迴圈 提供了更多的靈活性,適合需要對索引進行精細控制的場景。
類和物件
類:對物件向上抽取出像的部分、公共的部分一次形成類,類就相當於一個模板
物件:模板下具體的產物可以理解為具體的物件,物件就是一個一個及具體的例項,就相當於這個模板下具體的產品。
java中先定義類,在建立物件
類:
package com.day01.test3;
/*
* 人類
* */
public class Person {
// 特性-屬性-名詞
String name;
int age;
int height;
// 行為-方法-動詞
// 定義一個學習的方法
public void study(){
System.out.println("學海無涯苦作舟");
}
}
物件:
package com.day01.test3;
public class Test {
// 程式的入口(不是大類的程式入口是小類之間的呼叫)
public static void main(String[] args) {
//對Person類的物件建立,建立了一個Person物件
Person p1 = new Person();
p1.name = "李薇";
p1.age = 24;
p1.height = 180;
System.out.println(p1.name);
System.out.println(p1.age);
// 呼叫方法
p1.study();
}
}
構造器
對於一個類而言,一般有三種常見的成員:屬性方法、構造器、
這三種成員都可以定義零個或多個。
構造方法(構造器),是一個建立物件時被自動呼叫的特殊方法,用於物件的額初始化。java嘔吐難過new關鍵字來呼叫構造器,從而返回該類的例項。
類:
package com.day01.test3;
/*
* 人類
* */
public class Person {
// 特性-屬性-名詞
String name;
int age;
int height;
// 行為-方法-動詞
// 定義一個學習的方法
public void study(){
System.out.println("學海無涯苦作舟");
}
// 構造器的引數名字,如果和屬性名字重名,就會發生就近原則
// 如果重名,你想要給屬性賦值,那麼就在想要表達屬性的變數前加上this.來修價
public Person(){
System.out.println("45天秤神");
}
public Person(int age){
System.out.println("李薇的年齡為" + age);
this.age = age;
this.name = "王八蛋";
this.height = 156;
}
}
物件的生成:
package com.day01.test3;
public class Test2 {
public static void main(String[] args) {
/*
* 建立一個Persion類的物件
* 其中的Person是一個空的構造方法
* new關鍵字對方法進行呼叫 -》構造器的作用:底層就會自動幫我們建立物件之後,進行初始化的操作。
* 如果一個類沒有顯示編寫構造器的話,那麼系統會為這個類預設分配一個空的構造方法
* 呼叫構造器以後,對物件進行初始化作,將物件的地址返回給p
* 以後儘量保證空構造器的存在,以後學到框架,某些框架底層需要空構造器,如果你沒有新增就會報錯。
* 如果一個類中有構造器,那麼系統就不會幫你分配預設的空構造器
* */
Person p = new Person(20);
}
}
重點特性:
-
其中的Person是一個空的構造方法
-
new關鍵字對方法進行呼叫 -》構造器的作用:底層就會自動幫我們建立物件之後,進行初始化的操作。
-
如果一個類沒有顯示編寫構造器的話,那麼系統會為這個類預設分配一個空的構造方法
-
呼叫構造器以後,對物件進行初始化作,將物件的地址返回給p
-
以後儘量保證空構造器的存在,以後學到框架,某些框架底層需要空構造器,如果你沒有新增就會報錯。
-
如果一個類中有構造器,那麼系統就不會幫你分配預設的空構造器
構造方法也是方法,只不過有特殊的作用而已。與普通方法一樣,構造方法也可以過載。(一般都會進行過載一個空的構造方法)
封裝
我們程式設計追求“高內聚,低耦合
高內聚:類的內部資料操作細節自己完成,不允許外部干涉;
低耦合:僅對外暴露少量的方法用於使用。
隱藏物件內部的複雜性,只對外公開簡單的介面。便於外界呼叫,從而提高系
統的可擴充套件性、可維護性,提高程式的安全性。通俗的說,把該隱藏的隱藏起
來,該暴露的暴露出來。這就是封裝性的設計思想。
示例程式碼:
package com.day01.test4;
public class Girl {
private int age;
public void shezhiAge(int age){
if(age>18){
this.age = 18;
}else{
this.age = age;
}
}
public int Age(){
return this.age;
}
}
package com.day01.test4;
public class Tets {
public static void main(String[] args) {
Girl g = new Girl();
g.shezhiAge(33);
System.out.println(g.Age());
}
}
上述的程式碼就展示了內部高耦合,(透過函式範圍物件內部的資料與直接訪問內部的資料之間的區別),透過函式訪問內部的資料,開發者可以根據自己的意願對物件內部的資料進行限制。
alt+insert:能夠快捷生成get和set方法。
繼承
類是對物件的抽象
繼承是對類的抽象
超類/基類/父類:從眾多的類中在進行抽象出來的公共的類
繼承的格式:子類 extends 父類
繼承的好處:
1.提高了程式碼的複用性
2.便於程式碼的擴充套件
3.為了多型的使用,是多型使用的前提
示例程式碼:
package com.day01.test5;
public class Person {
//父類中的公共屬性
private int age;
private String name;
private double height;
// 父類中公共的方法
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//吃飯
public void eat(){
System.out.println("人類可以吃飯");
}
public void sleep(){
System.out.println("人類可以睡覺");
}
public void shout(){
System.out.println("人類可以喊叫");
}
}
package com.day01.test5;
public class Student extends Person{//子類student繼承父類Persoin
//定義子類額外的、擴充套件的方法
private int sno;
// 定義子類的額外的、擴充套件的方法
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
// 學習
public void study(){
System.out.println("學生可以進行學習");
}
}
package com.day01.test5;
public class Test {
public static void main(String[] args) {
//定義一個子類具體的物件
Student s = new Student();
s.setAge(10);
s.setSno(102030);
s.setName("雷偉");
s.setHeight(181.11);
s.study();
s.eat();
s.shout();
System.out.println(s.getAge());
}
}
方法的重寫
方法的重寫:
發生在子類和父類中,當子類對父類提供的方法不滿意的時候,
要對父類的方法進行重寫
方法的重寫有嚴格的格式要求:
子類的方法名字和父類必須一致,引數列表(個數,型別,順序)也要和父類一致。
過載和重寫的區別:
過載:在同一個類中,當方法名相同,形參列表不同的時候,多個方法構成了過載
重寫:在不同的類中,子類對父類提供的方法不滿意,對父類的方法進行重寫
多型
多型:通俗來說,就是多種形態,具體點就是去完成某個行為,當不同的物件
去完成時會產生出不同的狀態。同一種行為,不同的子類呈現出來的狀態是不
同的。
pwnda(自己的理解):多型是為了讓一個函式能夠傳入不同的引數(邏輯上的不同的引數)(前提這些執行的方法有著相同的抽象的父類),從而可以在相同的一個方法根據傳入引數的不同執行不同的效果。真正傳入的引數就是兩者共同的父類。(合成的寫法就是用子類來初始化這個父類的物件),
前提在子類中對父類的方法進行了重寫。並且在多型執行的函式中執行的就是重寫的方法
示例程式碼:
抽象的父類:
package com.day01.test7;
public class Animal {
public void shout(){
System.out.println("叫!!!!!!");
}
}
子類:
package com.day01.test7;
public class Dog extends Animal{
// 喊叫
public void shout(){
System.out.println("狗-汪汪叫");
}
public void guard(){
System.out.println("汪汪隊立大功");
}
}
子類:
package com.day01.test7;
public class Cat extends Animal{
public void shout(){
System.out.println("貓:喵喵喵叫");
}
public void scratch(){
System.out.println("貓抓人");
}
}
package com.day01.test7;
public class Test {
public static void main(String[] args) {
// 建立女孩的例項、物件:
Girl now = new Girl();
// 建立貓的例項
// Cat c = new Cat();
// Dog d = new Dog();
// now.play(c);
// now.play(d);
Animal an;//定義一個具體的動物
Cat c = new Cat();//具體的貓
an = c;//讓動物是一隻具體的貓
// 合成一句話:Animal an = new Cat();
now.play(an);
}
}
異常處理
try-catch-finally-throw-throws
異常就是在程式的執行過程中所發生的不正常的事件,它會中斷正在執行的程式。
所需檔案找不到
網路連線不通或中斷
算術運算錯 (被零除...)
陣列下標越界
裝載一個不存在的類或者對null物件操作
型別轉換異常
Java提供異常處理機制。它將異常處理程式碼和和業務程式碼分離,使程式更優雅,更好的
容錯性,高鍵壯性。
Java的異常處理是透過5個關鍵字來實現的:try、catch、finally、throw、throws
程式出錯捕獲之後可以繼續執行後面的程式碼
try-catch執行情況
情況1:try塊中程式碼沒有出現異常
不執行catch塊程式碼,執行catch塊後邊的程式碼
情況2:try塊中程式碼出現異常,catch中異常型別匹配(相同或者父類)
Java會生成相應的異常物件,Java系統尋找匹配的catch塊,執行catch塊程式碼,執行
catch塊後邊的程式碼。try塊中尚未執行的語句不會執行。
情況3:try塊中程式碼出現異常,catch中異常型別不匹配
不執行catch塊程式碼,不執行catch塊後邊的程式碼,程式會中斷執行
catch塊中如何處理異常
其中一種方式:自定義內容輸出
注:exception可以匹配所有的異常(是所有錯誤子類的父類)
示例:
package com.day01.test8;
public class Test1 {
public static void main(String[] args) {
try{
int num1 = 12;
int num2 = 0;
System.out.println("結果為:"+num1/num2);
}catch(Exception ex){
System.out.println("對不起,程式出現了錯誤" + ex);
}finally {
System.out.println("程式無論是否出現異常,這個邏輯都會執行的");
}
System.out.println("執行到這裡了!!!!!!!");
System.out.println("執行到這裡了!!!!!!!");
System.out.println("執行到這裡了!!!!!!!");
}
}
finally:無論程式中是否出現異常程式都會執行finally中的程式碼塊
throw:自己進行異常的丟擲
throws:將該異常拋給呼叫該函式的函式
throw和throws的區別:
(1)位置不同:
throw:方法內部
throws:方法的簽名處,方法的宣告處
(2)內容不同:
throw+異常物件
throws+異常的型別
(3)作用不同:
throw:異常出現的源頭,製造異常,
throws:在方法的宣告處,告訴方法的呼叫者,這個方法中可能會出現我宣告的這些異
常。然後呼叫者對這個異常進行處理:要麼自己處理要麼再繼續向外丟擲異常。
集合
陣列的缺點-》 集合的優點
- 陣列一旦指定了長度,那麼長度就被確定了,不可以更改。
- 刪除,增加元素 效率低。
- 陣列中實際元素的數量是沒有辦法獲取的,沒有提供對應的方法或者屬性來獲取
- 陣列儲存:有序、可重複,對於無序的,不可重複的場合陣列不能滿足要求