Java總結一


Java 基礎常識

  • Java 的跨平臺是通過什麼實現的?
    :java跨平臺是通過JVM(java 虛擬機)實現的。java 虛擬機:即Java Virtual Machine
    但JVM(java虛擬機)不是跨平臺的, sun公司針對不同的平臺分別設計不同的JVM 。
    注意:編譯的結果不是生成機器碼,而是生成字節碼,字節碼不能直接運行,必須通過
    JVM翻譯成機器碼才能運行。不同平臺下編譯生成的字節碼是一樣的,但是由JVM翻譯
    成的機器碼卻不一樣。
  • JDK、JRE、JVM 的全稱是什麼?
    : JDK(Java Development Kit) 是 Java 語言的軟件開發工具包; JRE(Java Runtime En
    vironment,Java運行環境),運行JAVA程序所必須的環境的集合,包含JVM標準實現及
    Java核心類庫; JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用於計
    算設備的規範,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算
    機功能來實現的。
  • public class 的類名必須跟文件名保持一致嗎?
    : 1.java保存的文件名必須與類名一致;
    2.如果文件中只有一個類,文件名必須與類名一致;
    3.一個Java文件中只能有一個public類;
    4.如果文件中不止一個類,文件名必須與public類名一致;
    5.如果文件中不止一個類,而且沒有public類,文件名可與任一類名一致。
  • 一個 Java 源文件可以寫多個 Class 嗎?編譯後會不會生成多個 Class 文件?
    : 一個JAVA源文件裏面可以有內部類,其他類(有且僅有一個類可以聲明爲public),所以,
    編譯後,可以有多個class文件。
  • 編程時,爲什麼需要註釋?Java 中註釋的類型有哪些?
    : 1. 應用編碼規範對於軟件本身和軟件開發人員而言尤爲重要,其中註釋就是非常重要的一部
    分了。你的註釋不僅僅可以幫助你理解代碼含義,還有利於測試人員測試代碼,更加重要的
    是它在後期生成文檔,下一次看代碼可以節約不少時間和精力。
    2.對於Java註釋我們主要了解三種: 1. // 註釋一行 2./* …… / 註釋若干行 3./*……*/文檔
    註釋 /* …… / 註釋若干行,並寫入 javadoc文檔,java圖標通常這種註釋的多行寫法如下:
    /*    ………   * ………   */

面向對象(一)

  • 簡述面向對象和麪向過程的區別和聯繫?
    : 面向過程就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候
    一個一個依次調用就可以了。 面向對象是把構成問題事務分解成各個對象,建立對象的目的不是
    爲了完成一個步驟,而是爲了描敘某個事物在整個解決問題的步驟中的行爲。 面向過程的編程應
    該關注的是如何使用函數去實現既定的功能。面向對象的編程,是關注如何把相關的功能,包括
    函數和數據有組織地捆綁到一個對象身上。例如五子棋,面向過程的設計思路就是首先分析問題
    的步驟:1、開始遊戲,2、黑子先走,3、繪製畫面,4、判斷輸贏,5、輪到白子,6、繪製畫面
    7、判斷輸贏,8、返回步驟2,9、輸出最後結果。把上面每個步驟用分別的函數來實現,問題就
    解決了。 而面向對象的設計則是從另外的思路來解決問題。整個五子棋可以分爲 1、黑白雙方,
    這兩方的行爲是一模一樣的,2、棋盤系統,負責繪製畫面,3、規則系統,負責判定諸如犯規、
    輸贏等。第一類對象(玩家對象)負責接受用戶輸入,並告知第二類對象(棋盤對象)棋子佈局
    的變化,棋盤對象接收到了棋子的i變化就要負責在屏幕上面顯示出這種變化,同時利用第三類對
    象(規則系統)來對棋局進行判定。可以明顯地看出,面向對象是以功能來劃分問題,而不是步驟。
    同樣是繪製棋局,這樣的行爲在面向過程的設計中分散在了總多步驟中,很可能出現不同的繪製版
    本,因爲通常設計人員會考慮到實際情況進行各種各樣的簡化。而面向對象的設計中,繪圖只可能
    在棋盤對象中出現,從而保證了繪圖的統一。 功能上的統一保證了面向對象設計的可擴展性。比如
    我要加入悔棋的功能,如果要改動面向過程的設計,那麼從輸入到判斷到顯示這一連串的步驟都要
    改動,甚至步驟之間的循序都要進行大規模調整。如果是面向對象的話,只用改動棋盤對象就行了
    ,棋盤系統保存了黑白雙方的棋譜,簡單回溯就可以了,而顯示和規則判斷則不用顧及,同時整個
    對對象功能的調用順序都沒有變化,改動只是局部的。
    再比如我要把這個五子棋遊戲改爲圍棋遊戲,如果你是面向過程設計,那麼五子棋的規則就分佈在
    了你的程序的每一個角落,要改動還不如重寫。但是如果你當初就是面向對象的設計,那麼你只用
    改動規則對象就可以了,五子棋和圍棋的區別不就是規則嗎?(當然棋盤大小好像也不一樣,但是
    你會覺得這是一個難題嗎?直接在棋盤對象中進行一番小改動就可以了。)而下棋的大致步驟從面
    向對象的角度來看沒有任何變化。 當然,要達到改動只是局部的需要設計的人有足夠的經驗,使用
    對象不能保證你的程序就是面向對象,初學者或者很蹩腳的程序員很可能以面向對象之虛而行面向
    過程之實,這樣設計出來的所謂面向對象的程序很難有良好的可移植性和可擴展性。
    這兩種不同的設計思想使得在運用這兩種思想編程時粒度相差很大:面向對象的程序單位是類,而
    面向過程的 程序單位是函數,使得它比面向對象過程更復雜。
    而兩者的聯繫又體現在都是在對數據進行處理,只是面向對象站在更高的角度上,將數據和函數打
    包,在對象的層次上去處理。
    實際實現一個 對象的過程中,就包含了很多面向過程的方法。
    來源: https://zhidao.baidu.com/question/587576019136886805.html

  • 對象和類的關係時?
    : 對象是對客觀事物的抽象,類是對對象的抽象。類是一種抽象的數據類型,其定義爲:class 類名{ }
    它們的關係是,對象是類的實例,類是對象的模板。

  • 堆和棧的特點是什麼?分別存放什麼內容?
    : 堆――heap;棧――stack;棧是機器系統提供的數據結構,而堆是由C/C++函數庫提供的;1、從
    數據結構層次理解,棧是一種先進後出的線性表,只要符合先進後出的原則的線性表都是棧。至於採
    用的存儲方式(實現方式)是順序存儲(順序棧)還是鏈式存儲(鏈式棧)是沒有關係的。堆則是二
    叉樹的一種,有最大堆最小堆,排序算法中有常用的堆排序。2、 從系統層次理解,棧是系統爲運行
    的程序分配的先進後出的存儲區域。在學習bootloader時知道,在上電後初始化階段要爲各個工作模
    式下分配堆 棧,這裏的堆棧實際上就是指stack,堆棧的說法只是因爲歷史的原因。在執行函數時,
    函數內部局部變量的存儲單元可以在棧上創建(針對CISC架構而 言,RISC架構下,局部變量的存儲
    單元是在寄存器上創建),函數執行結束時這些存儲單元自動被釋放。堆是系統管理的可以被程序利
    用的全局存儲空間,動態 內存分配就是從堆上分配。
    總結:
    1、棧是系統提供的功能,特點是快速高效,缺點是有限制,數據不靈活;而堆是函數庫提供的功能,
    特點是靈活方便,數據適應面廣泛,但是效率有一定降低。
    2、棧是系統數據結構,對於進程/線程是唯一的;堆是函數庫內部數據結構,不一定唯一,不同堆分
    配的內存無法互相操作。
    3、棧空間分靜態分配和動態分配兩種。靜態分配是編譯器完成的,比如自動變量(auto)的分配。動
    態分配由alloc函數完成。棧的動態分配無需釋放 (是自動的),也就沒有釋放函數。爲可移植的
    程序起見,棧的動態分配操作是不被鼓勵的!堆空間的分配總是動態的,雖然程序結束時所有的
    數據空間都會被釋放 回系統,但是精確的申請內存/釋放內存匹配是良好程序的基本要素。
    來源: http://blog.csdn.net/yahohi/article/details/8035996
  • 局部變量使用之前,需要手動初始化嗎?
    :成員變量可以不用初始化,其具有默認值;但是局部變量一定需要初始化或者賦值後才能使用,否則編
    譯報錯。
    可能的原因如下,當我們新建一個對象時,Java會在Heap中申請一塊內存區域用以存放類的數據。而
    成員變量就是類的數據,也是放在這塊內存區域中的。只需要JVM在申請內存的時候順便把整塊區域都
    置爲零即可完成初始化,方便快捷。而對於方法的局部變量,是在線程的Stack中,當然Stack他也可以
    幫我們初始化,不過有一個問題。對於有些局部變量,在方法的一開始是沒有的,有些在循環中的局部
    變量是要反覆的聲明多次的。有些局部變量作用域結束後,另一個局部變量又會佔用這個局部變量的位
    置。
    來源: http://blog.csdn.net/rockpk008/article/details/52124461
  • Java 中如果不手動指定成員變量的值,系統會自動初始化,那麼初始化的規則是?

    基本數據類型 默認值
    byte 0
    short 0
    int 0
    long 0L
    char \u0000(空格)
    float 0.0f
    double 0.0d
    boolean false
    所有引用類型的初始化值爲null。 class interface array;
    注意:java自己不會執行局部變量的初始化,需要人爲賦值,纔可以使用。
    但是,定義一個局部的數組: int[] arr =new int[5] ;
    其中的元素也被賦上默認初始值,打印結果爲0,看來數組還真是不簡單。
    百度後發現和new關鍵字有關,並且需要掌握內存中的棧和堆。原來,內存
    中分爲堆內存和棧內存,程序開始時,main方法進棧,在堆內存中分配空間
    創建的成員變量;局部變量保存在棧中。 創建數組則是在堆中,分配空間後
    默認初始化值。 我覺得可以這樣認爲,在堆內存中分配空間的變量都會java

都會自動初始化值,像成員變量。

  • 構造方法如何被調用?
    :新建一個對象是被調用。也就是new的時候;如:
    public class A {
    int i;
    String c;
    public A() { } //無參構造方法
    public A (int i, String c) { // 兩參構造方法
    this.i = i;
    this.c = c;
    }
    public static void main(String[] args) {
    A a = new A() ; //調用了無參構造方法;
    A a1 = new A(5,”vieri”); //調用了兩參構造方法
    }
    }
    來源: http://blog.csdn.net/woshixuye/article/details/7214976
  • 系統一定會給我們添加無參數的構造方法嗎?請詳細解釋。
    : 每個類在沒有聲明構造方法的前提下,會自動生成一個不帶參數的構造方法,如果
    類一但聲明有構造方法,就不會產生了.
    可證:
    class person
    {
    person(){System.out.println(“父類-person”);}
    person(int z){}
    }
    class student extends person
    {
    // student(int x ,int y){super(8);}
    }

class Rt
{
public static void main(String[]args)
{
student student_dx=new student();//創建student類的對象
}
}
//輸出結果:父類-person
來源: http://blog.csdn.net/stellaah/article/details/6718178
例說明:student類自動生成student() {super();}(前提是:student類沒有聲明構造方法的前提下) ‘super()’是用來調用父類的構造方法.
- 構造方法能不能重載?
: 可以,同名不同參
- this 在普通方法中,指的是哪個對象?在構造方法中,指的是?
: this 在普通方法中,指的是調用該方法的對象,在構造方法中,指的是調用該構造方法的對象。
- 靜態初始化塊和 main 方法哪個先被執行?
: 靜態初始化塊比main方法先執行;
補充:
所有的靜態初始化塊都優先執行,其次纔是非靜態的初始化塊和構造函數,它們的執行順序是
父類的靜態初始化塊子類的靜態初始化塊父類的初始化塊父類的構造函數子類的初始化塊子類
的構造函數,靜態代碼塊是:屬於類的,在類加載時就自動執行。靜態代碼塊定義時不能添加
作用域符。構造塊是: 在類中定義的,且定義的位置與該類的其他的屬性是相當的,就是不在
該類的任何成員方法中,定義時直接用{ }包含即可,不用再添加其他任何的訪問作用域符。構
造塊是每次創建對象都會執行一次構造塊。普通代碼塊:定義位置實在方法內部,在方法體內
用 { } 包含即可。


  • 一個構造方法調用另一個構造方法怎麼調用?this() 這樣的調用方式必須位於第一句嗎?
    : this或者super;實例方法中可以使用this關鍵字,它指向正在執行方法的類的實例對象,當然static
    方法中是不可以使用this對象的,因爲靜態方法不屬於類的實例對象;而構造方法中同樣可以使用
    this關鍵字,構造器中的this是指向同一個對象中不同參數的另一個構造器。
    public class Platypus {
    String name;

    Platypus(String input) {
    name = input;
    }

    Platypus() {
    this(“John/Mary Doe”);
    }

    public static void main(String args[]) {
    Platypus p1 = new Platypus(“digger”);
    Platypus p2 = new Platypus();
    System.out.println(p1.name + “—-” + p2.name);
    }
    }
    上面的代碼中 類有兩個構造器,第一個構造器給類的成員name賦值,第二個構造器調用第一個構造器給類
    的成員name一個初始值Jonn/Mary Doe
    所以程序執行結果:digger—-John/Mary Doe
    需要注意的兩個地方是:
    1、構造方法中通過this關鍵字調用其他構造方法時,那麼這句代碼必須放在第一行,否則會編譯錯誤。
    2、構造方法中只能通過this調用一次其他的構造方法。”super”的用法:
    實例方法和構造方法中的super關鍵字都用於去指向父類,實例方法中的super關鍵字是去調用父類當中的某個方法,看
    下面的代碼:
    class getBirthInfo {
    void getBirthInfo() {
    System.out.println(“born alive.”);
    }
    }

class Platypus1 extends getBirthInfo
{
void getBirthInfo() {
System.out.println(“hatch from eggs”);
System.out.println(“a mammal normally is “);
super.getBirthInfo();
}
}

public class test1 {
public static void main(String[] args) {
Platypus1 p1=new Platypus1();
p1.getBirthInfo();
}
}
上面的例子使用super.getBirthInfo();調用了它的父類的void getBirthInfo()方法。
構造器中使用super關鍵字調用父類中的構造器,看下面的代碼:
class getBirthInfo {
getBirthInfo(){
System.out.println(“auto”);
}
void aa() {
System.out.println(“born alive.”);
}
}

class Platypus1 extends getBirthInfo
{
Platypus1() {
super();
System.out.println(“hatch from eggs”);
System.out.println(“a mammal normally is “);
}
}

public class test1 {
public static void main(String[] args) {
Platypus1 p1=new Platypus1();
}
}
執行了代碼我們就會看到構造器中的super調用了父類的構造方法。

類的繼承機制使得子類可以調用父類的功能,下面介紹類在繼承關係的初始化順序問題

請看實例1:
class SuperClass
{
SuperClass()
{
System.out.println(“SuperClass constructor”);
}
}
public class SubClass extends SuperClass {
SubClass()
{
System.out.println(“SubClass constructor”);
}
public static void main(String[] args) {
SubClass sub = new SubClass();
}
}
執行結果:SuperClass constructor
SubClass constructor
代碼中我們只實例化子類一個對象,但從執行結果上看程序一開始並不是運行子類的構造方法,而是先執行父類的默認構造方法,然後再執行子類的構造方法.所以我們在實例化子類對象時,程序會先調用父類的默認構造方法,然後再執行子類的構造方法。

再看實例2:
class SuperClass
{
SuperClass(String str)
{
System.out.println(“Super with a string.”);
}
}
public class SubClass extends SuperClass
{
SubClass(String str)
{
System.out.println(“Sub with a string.”);
}

public static void main(String[] args)   
{   
SubClass sub = new SubClass("sub");   
}   

}
注意:此程序在JDK下不能編譯成功,因爲我們在實例化子類對象的時候會先調用其父類默認的構造方法(除非實例化對象的構造函數中有調用任意的父類構造方法),但是它的父類沒有默認的構造方法,所以不能編譯成功。易錯地方!!
解決辦法:
1、在父類中加一個顯示的默認構造方法
2、在子類的構造方法中加一句super(str)並且必須在構造器的第一句。
兩個辦法都可以解決程序編譯的問題,但是執行結果是不一樣的.
第一種執行結果爲:Sub with a string.
第二種執行結果爲:Super with a string.
Sub with a string. 第二種方法即使父類中有顯示的默認構造方法也不會被調用。
- package 的兩個作用是什麼?

1、把功能相似或相關的類或接口組織在同一個包中,方便類的查找和使用。
2、如同文件夾一樣,包也採用了樹形目錄的存儲方式。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時調用兩個不同包中相同類名的類時,應該加上包名加以區別。因此,包可以避免名字衝突。
3、包也限定了訪問權限,擁有包訪問權限的類才能訪問某個包中的類。
- import statis 叫做靜態導入,那麼其作用是什麼?
: 導入靜態成員;import static靜態導入是JDK1.5中的新特性。一般我們導入一個類都用 import com…..ClassName;而靜態導入是這樣:import static com…..ClassName.*;這裏的多了個
static,還有就是類名ClassName後面多了個 .* ,意思是導入這個類裏的靜態方法。當然,也可
以只導入某個靜態方法,只要把 .* 換成靜態方法名就行了。然後在這個類中,就可以直接用方法名
調用靜態方法,而不必用ClassName.方法名 的方式來調用。

這種方法的好處就是可以簡化一些操作,例如打印操作System.out.println(…);就可以將其寫入一個靜態方法print(…),在使用時直接print(…)就可以了。 在靜態導入之前:
public class TestStatic {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toHexString(42));
}
}
在靜態導入之後:
import static java.lang.System.out;
import static java.lang.Integer.*;

public class TestStaticImport {
public static void main(String[] args) {
out.println(MAX_VALUE);
out.println(toHexString(42));
}
}
兩個類都產生相同的輸出:
2147483647
2a
來源: http://blog.sina.com.cn/s/blog_764e06170101ahrq.html

但是這種方法建議在有很多重複調用的時候使用,如果僅有一到兩次調用,不如直接寫來的方便
來源: http://www.cnblogs.com/lushilin/p/5288860.html
- 請詳細快速的說明 private、default、protected、public 的區別。

修飾符 類內部 本包 子類 外部包
public √ √ √ √
protected √ √ √ X
default √ √ X X
private √ X X X
- javabean 就是隻包含屬性和相關 getter/setter 方法,不包含業務邏輯處理的被,這種說法對嗎?
: 可以包含;
JavaBean實際上是指一種特殊的Java類,它通常用來實現一些比較常用的簡單功能,並可
以很容易的被重用或者是插入其他應用程序中去。所有遵循“一定編程原則”的Java類都可以
被稱作JavaBean。
◆JavaBean是一個遵循特定寫法的Java類,是一種Java語言編寫的可重用組件,它的方法命
名,構造及行爲必須符合特定的約定:
1、這個類必須具有一個公共的(public)無參構造函數;
2、所有屬性私有化(private);
3、私有化的屬性必須通過public類型的方法(getter和setter)暴露給其他程序,並且方法的
命名也必須遵循一定的命名規範。
4、這個類應是可序列化的。(比如可以實現Serializable 接口,用於實現bean的持久性)

   ◆JavaBean在Java EE開發中,通常用於封裝數據,對於遵循以上寫法的JavaBean組件,其它程序可以通過反射              技術實例化JavaBean對象(內省機制),並且通過反射那些遵循命名規範的方法,從而獲知JavaBean的屬性,            進而調用其屬性保存數據。

因爲這些要求主要是靠約定而不是靠實現接口,所以許多開發者把JavaBean看作遵從特定命名約定的POJO。(可以這麼理解,POJO按JavaBean的規則來,就可以變成JavaBean)。

◆簡而言之,當一個POJO可序列化,有一個無參的構造函數,使用getter和setter方法來訪問屬性時,他就是一個JavaBean。(沒毛病!)


JavaBean是一種組件技術,就好像你做了一個扳手,而這個扳手會在很多地方被拿去用,這個扳子也提供多種功能(你可以拿這個扳手扳、錘、撬等等),而這個扳手就是一個組件。

◇對於JavaBean,就是一個Java模型組件,他爲使用Java類提供了一種標準的格式,在用戶程序和可視化管理工具中可以自動獲得這種具有標準格式的類的信息,並能夠創建和管理這些類。
◇JavaBean可以使應用程序更加面向對象,可以把數據封裝起來,把應用的業務邏輯和顯示邏輯分離開,降低了開發的複雜程度和維護成本!
◇JavaBean 是一種JAVA語言寫成的可重用組件。爲寫成JavaBean,類必須是具體的和公共的,並且具有無參數的構造器。JavaBeans 通過提供符合一致性設計模式的公共方法將內部域暴露稱爲屬性。衆所周知,屬性名稱符合這種模式,其他Java 類可以通過內省機制發現和操作這些JavaBean 屬性。
◇通常情況下,由於 Java Bean 是被容器所創建(如 Tomcat) 的,所以 Java Bean 應具有一個無參的構造器,另外,通常 Java Bean 還要實現 Serializable 接口用於實現 Bean 的持久性。 Java Bean 是不能被跨進程訪問的。
◇JavaBean 是使用 java.beans 包開發的,它是 Java 2 標準版的一部分。JavaBean 是一臺機器上同一個地址空間中運行的組件。JavaBean 是進程內組件。
來源: http://blog.csdn.net/chenchunlin526/article/details/69939337#comments


-構造方法和實例方法的區別
:主要的區別在於三個方面:修飾符、返回值、命名
1、和實例方法一樣,構造器可以有任何訪問的修飾符,public、private、protected或者
沒有修飾符,都可以對構造方法進行修飾。不同於實例方法的是構造方法不能有任何
非訪問性質的修飾符修飾,例如static、final、synchronized、abstract等都不能修
飾構造方法。
解釋:構造方法用於初始化一個實例對象,所以static修飾是沒有任何意義的;多個線程不會同時創建內存地 址相同的同一個對象,所以synchronized修飾沒有意義;
構造方法不能被子類繼承,所以final和abstract修飾沒有意義。
2、返回類型是非常重要的,實例方法可以返回任何類型的值或者是無返回值(void),而構造方法是沒有返回 類型的,void也不行。
3、至於命名就是構造方法與類名相同,當然了實例方法也可以與類名相同,但是習慣上我們爲實例方法命名的時 候通常是小寫的,另一方面也是與構造方法區分開。
而構造方法與類名相同,所以首字母一般大寫。
來源: http://blog.csdn.net/zmissm/article/details/14176725

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