複習之路之JAVA基礎知識概括

摘抄自公開的筆記,一部分做自我補充。

1. 面向對象和麪向過程的區別

面向過程 : 面向過程性能比面向對象高。 因爲類調用時需要實例化,開銷比較大,比較消耗資源,所以當性能是最重要的考量因素的時候,比如單片機、嵌入式開發、Linux/Unix 等一般採用面向過程開發。但是,面向過程沒有面向對象易維護、易複用、易擴展。
面向對象 :面向對象易維護、易複用、易擴展。 因爲面向對象有封裝、繼承、多態性的特性,所以可以設計出低耦合的系統,使系統更加靈活、更加易於維護。但是,面向對象性能比面向過程低。

Java 是一種兼具編譯和解釋特性的語言,.java 文件會被編譯成與平臺無關的 .class 文件,但是 .class 字節碼文件無法被計算機直接,仍然需要 JVM 進行翻譯成機器語言。 所以嚴格意義上來說,Java 是一種半解釋半編譯型語言。這也是java比其他面向過程語言性能低的原因之一,面向過程語言大多都是直接編譯成機械碼在電腦上執行,並且其它一些面向過程的腳本語言性能也並不一定比 Java 好。

2.那你來說說什麼是封裝,繼承,多態

封裝是在抽象的基礎上決定信息是否公開,以及公開等級,核心問題是以什麼樣的方式公開哪些信息。
抽象是要找到屬性和行爲的共性,屬性是行爲的基本生產資料,具有一定的敏感性,不能直接對外暴露,所以說封裝的主要任務就是對屬性,數據和部分敏感行爲實現隱藏。對屬性的訪問和修改必須通過定義的公共接口來操作。
繼承是面嚮對象的技術基礎,允許創建具有邏輯體系結構的類體系,讓軟件在業務多變的客觀條件下,某些基礎模塊可以被直接,間接,或者增強的複用。父類的能力通過繼承賦予子類,繼承爲多態打下語法基礎。
多態是根據運行時的實際運行對象,同一個方法產生不同的運行結果,使同一個行爲具有不同的表現形式。

說到多態就 就關係到override和overload,前者是子類重寫父類的方法或者實現 的接口方法,而後者是在同一個類時方法名稱相同法具有不同參數或者返回值的形式。(但是不能只是以返回值不同來區分重載的方法),假如我們調用方法的時候,不接受他的結果,恐怕你自己也不知道執行的是哪個方法吧

JDK JVM JRE

Java 虛擬機(JVM)是運行 Java 字節碼的虛擬機。JVM 有針對不同系統的特定實現(Windows,Linux,macOS),目的是使用相同的字節碼,它們都會給出相同的結果。
在這裏插入圖片描述
JDK 是 Java Development Kit,它是功能齊全的 Java SDK。它擁有 JRE 所擁有的一切,還有編譯器(javac)和工具(如 javadoc 和 jdb)。它能夠創建和編譯程序
JRE Java Runtime Environment 是 Java 運行時環境。它是運行已編譯 Java 程序所需的所有內容的集合,包括 Java 虛擬機(JVM),Java 類庫,java 命令和其他的一些基礎構件。但是,它不能用於創建新程序。

字符型常量Char和字符串String常量的區別?

形式上: 字符常量是單引號引起的一個字符; 字符串常量是雙引號引起的若干個字符
含義上: 字符常量相當於一個整型值( ASCII 值),可以參加表達式運算; 字符串常量代表一個地址值(該字符串在內存中存放位置)
佔內存大小 字符常量只佔 2 個字節; 字符串常量佔若干個字節 (注意: char 在 Java 中佔兩個字節)

那麼JAVA有幾種基本類型?

boolean(8位),byte(8位),char(16位),short(16位),int(32位),long(64),float(32),double(64).
在類中作爲變量的時候都會 默認值。
除了浮點類型和boolean,他們都有緩存區間。
64位的數據理論上在32位JVM上不能保證原子性。

上面說的緩存區間又是什麼啊?

上面說的緩存區間,是指他們的包裝類有緩存區間。包裝類可以完成基本數據類型不能做的事情。
比如:泛型參數,序列化,類型轉換,緩存。
上面的基本類型的的緩存區間byte,short,int,long在【-128,127】char在【0,127】,浮點和boolean沒有。

public class CacheTest(){
	public static void main(String[] args){
	Long a = 127L;
	Long b = 127L;
	(a == b);//true,二者在緩存池中,是複用的緩存池的現象
	Long a1 = 128L;
	Long b2 = 128L;
	(a1 == b1);//false,不在緩存中,都是新生成的對象
	}
}

String的緩存池

爲什麼String要單獨說,他不是基本類型呀!String不是基本類型
創建字符串的三類方式:

1、String s=new String(“abc”);

2、直接指定:String s=“abc”;

3、用字符串生成新的字符串:String s=“ab”+c;

String對象創建的原理:

(1)、當使用任何一種方法創建一個字符串對象s時,java運行時會拿這個s在string池中找是否存在相同的內容的字符串對象,如果不存在,則在池中創建一個字符串s,否則,不在池中添加。

(2)、java中,只要使用new關鍵字來創建對象,則一定會創建一個新的對象。

(3)、使用直接指定或者使用純字符串串聯來創建String對象,但僅僅會維護string池中的字符串,池中沒有就在池中創建一個,有則罷了,絕不會再堆棧區再去創建該String對象。

(4)、使用包含變量的表達式來創建String,則不僅會維護String池,而且還會在堆棧區創建一個String對象。

String StringBuffer 和 StringBuilder 的區別是什麼? String 爲什麼是不可變的?

String,StriingBuffer是線程安全的,StringBuilder不是。
可變性

簡單的來說:String 類中使用 final 關鍵字修飾字符數組來保存字符串,private final char value[],所以 String 對象是不可變的。
啥?

String str = "a" ;
str = "b";
str.sout();//我不是改變了嗎?

其實不然,JDK8 String 通過char數組實現,通過final修飾,str = b的操作只是重新創建了一個對象然後將str的 指針指向b,原先的a還是沒有被改變。(出門右轉百度final的內存語義)
以下代碼:

String sstr = "start";
for(int i = 0,i<100; i++){
str =  str +"h";
}

內部實現是每次 循環都要new一個StringBuilder的對象,然後通過append操作,最後通過ToString返回,性能差,浪費資源。

對於三者使用的總結:

操作少量的數據: 適用 String
單線程操作字符串緩衝區下操作大量數據: 適用 StringBuilder
多線程操作字符串緩衝區下操作大量數據: 適用 StringBuffer

自動裝箱與拆箱

裝箱:將基本類型用它們對應的引用類型包裝起來;
拆箱:將包裝類型轉換爲基本數據類型;
爲什麼要搞這麼多幺蛾子?
在JAVA中一切都是對象,但是基本數據類型他就不是對象。

List<Integer> list = new ArrayList<>();//行!Integer是對象
List<int>list = new ArrayList<>();//代碼報錯,int不是對象

在一個靜態方法內調用一個非靜態成員爲什麼是非法的?

類的靜態成員(變量和方法)屬於類本身,在類加載的時候就會分配內存,可以通過類名直接去訪問;非靜態成員(變量和方法)屬於類的對象,所以只有在類的對象產生(創建類的實例)時纔會分配內存,然後通過類的對象(實例)去訪問。
所以:

Person{
public static String staticStr  = "str";
public String str = "str";
public static void  test(){
//這裏訪問不到str 報錯
 this.str =
}
public void test2(){
this.staticStr//能訪問
}
}

爲什麼?你想想前面說的先後順序,加載類值加載類的靜態方法變量的時候實例化都還沒有開始,他拿命去訪問?
實例化完成自然可以訪問到靜態的。

在 Java 中定義一個不做事且沒有參數的構造方法的作用

Java 程序在執行子類的構造方法之前,如果沒有用 super()來調用父類特定的構造方法,則會調用父類中“沒有參數的構造方法”。因此,如果父類中只定義了有參數的構造方法,而在子類的構造方法中又沒有用 super()來調用父類中特定的構造方法,則編譯時將發生錯誤,因爲 Java 程序在父類中找不到沒有參數的構造方法可供執行。解決辦法是在父類里加上一個不做事且沒有參數的構造方法。

接口和抽象類的區別是什麼?

碼處高效56頁,57頁。
在這裏插入圖片描述
在這裏插入圖片描述

成員變量與局部變量的區別有哪些?

從語法形式上看:成員變量是屬於類的,而局部變量是在方法中定義的變量或是方法的參數;成員變量可以被 public,private,static 等修飾符所修飾,而局部變量不能被訪問控制修飾符及 static 所修飾;但是,成員變量和局部變量都能被 final 所修飾。
從變量在內存中的存儲方式來看:如果成員變量是使用static修飾的,那麼這個成員變量是屬於類的,如果沒有使用static修飾,這個成員變量是屬於實例的。而對象存在於堆內存,局部變量則存在於棧內存。
從變量在內存中的生存時間上看:成員變量是對象的一部分,它隨着對象的創建而存在,而局部變量隨着方法的調用而自動消失。
成員變量如果沒有被賦初值:則會自動以類型的默認值而賦值(一種情況例外:被 final 修飾的成員變量也必須顯式地賦值),而局部變量則不會自動賦值。

在調用子類構造方法之前會先調用父類沒有參數的構造方法,其目的是?

幫助子類做初始化工作。

1.首先加載父類的靜態字段或者靜態語句塊

2.子類的靜態字段或靜態語句塊

3.父類普通變量以及語句塊

4.父類構造方法被加載

5.子類變量或者語句塊被加載

6.子類構造方法被加載

== 與 equals

== 比較的就是hashcode
hashcode 和equals用來標誌對象,兩個方法協同比較兩個對象是否相等。
衆所周知,不同對象hash可能會相同,hash相同再用equals比較他們的值,如果值不同纔是真的不是同一個對象。如果hash都不同了,那麼肯定不是形同的對象。

所以:
equals比較的值同的對象,hash必然相同
重寫equals必須重寫hashcode

加入你定義了這麼一個類,

person p1 = new person("付有傑","身份證號碼");
person p2 = new person("付有傑","身份證號碼");

表面上看,明明想表達的就是全國唯一指定的付有傑,但是他們是同一個對象嗎?不是,他們的地址都不一樣。
如果你用p1做鍵存在set中,那麼在你存入p2的時候,他必定會在新的位置。

set.add(p1);
set.add(p2);
set.size();//我們期望是1 但是卻是2

所以我們還要重寫hashcode,使p1,p2 得出hashcode是一樣的。

其他的 多線程,IO,集合,異常體西,另開文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章