java匿名对象赋初值_不想进BAT的Java程序员不是好程序员,BAT后端Java岗面试真题分享
一. JDK/JRE/JVM 三者之間的聯系與區別
- JDK:開發者提供的開發工具箱,是給程序開發者用的。它包括完整的JRE(Java Runtime Environment),Java運行環境,還包含了其他供開發者使用的工具包。
- JRE:(Java Runtime Environment) JVM運行時所須的包依賴的環境都在JRE中。
- JVM:當我們運行一個程序時,JVM負責將字節碼轉換為特定機器代碼,JVM提供了內存管理、垃圾回收和安全機制等。這種獨立于硬件和操作系統,正是Java程序可以一次編寫多處執行的原因。
二. Java 面向對象編程的三大特性
2.1 封裝
封裝把一個對象的屬性私有化,同時提供一些可以被外界訪問的屬性和方法,如果屬性不想被外界訪問,我們大可不必提供方法給外界訪問。但是如果一個類沒有供外界訪問的方法,那么這個類也就沒有什么意義了。
2.2 繼承
繼承是使用已存在的類的定義作為基礎建立新類的技術,新類的定義可以增加新的數據或者新的功能,也可以用父類的功能,但不能選擇性的繼承父類。通過使用繼承我們能夠非常方便地復用以前的代碼。
關于繼承如下三點需要記住:
- 子類擁有父類非private的屬性和方法。
- 子類可以擁有自己的屬性和方法,即子類可以對父類進行擴展。
- 子類可以用自己的方式實現父類的方法。
2.3 多態
所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用,在編程時并不確定,而是在程序運行期間才確定。即一個引用變量到底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。在Java中有兩種形式可以實現多態:繼承(多個子類對同一方法的重寫)和接口(實現接口并覆蓋接口中的同一方法)
三. 面向對象與面向過程
3.1、面向過程
- 優點:性能比面向對象強,因為類調用時需要實例化,開銷比較大,比較消耗資源;比如單片機、嵌入式開發、Linux/Unix等一般采用面向過程開發,性能是最重要的因素。
- 缺點:沒有面向對象易維護、易復用、易擴展。
3.2、面向對象
- 優點:易維護、易復用、易擴展。由于面向對象有封裝、繼承、多態的三大特性,可以設計出低耦合的系統,使系統更加靈活、更加易于維護。
- 缺點:性能比面向過程低。
四. Java 語言有哪些特點
- 簡單易學;
- 面向對象(封裝、繼承、多態);
- 平臺無關性(Java虛擬機實現平臺無關性);
- 可靠性;
- 安全性;
- 支持多線程;
- 很方便的支持網絡編程;
- 編譯與解釋并存;
五. Java和C++的區別
沒學過C++,不代表面試官也沒學過
- 都是面向對象的語言,都支持封裝、繼承和多態
- Java不提供指針來直接訪問內存,程序內存更加安全
- Java的類是單繼承的,C++支持多重繼承;雖然Java的類不可以多繼承,但是接口可以多繼承。
- Java有自動內存管理機制,不需要程序員手動釋放無用內存。
六. Java 基本數據類型
Javabyteshortintlongdoublefloatcharboolean字節大小12488421占位大小81632646432168
- 整數類型:byte、short、int、long
- 字符型:char
- 浮點類型:float、double
- 布爾型:boolean
注意:
整數型默認int型。小數型默認是double型。float和long類型必須加后綴。
比如:float f=100f。
七. 成員變量與局部變量的區別
從語法形式上看:
- 成員變量是屬于類的,而局部變量是在方法中定義的變量或是方法的參數;
- 成員變量可以被public、private、static等修飾符所修飾,而局部變量不能被訪問控制修飾符及static所修飾。但是,成員變量和局部變量都能被final所修飾。
從變量在內存中的存儲方式來看:
- 如果成員變量是使用的 static修飾的,那么這個成員變量是屬于類的,如果沒有使用 static修飾,這個成員變量是屬于實例(對象)的。而對象存在與堆內存中、局部變量則存在于棧內存中。
從變量在內存中的生存時間上看:
- 成員變量是對象的一部分。它隨著對象的創建而存在,而局部變量隨著方法的調用而自動消失。
- 成員變量如果沒有被賦初值,則會自動以類型的默認值而賦值(一種情況例外:被final修飾的成員變量也必須顯示的賦值),而局部變量則不會自動賦值。
八. 靜態方法和實例方法有何不同
在外部調用靜態方法時,可以使用“類名.方法名”的方式,也可以使用“對象名.方法名”的方式。而實例方法只有后面這種方式。也就是說,調用靜態方法可以無需創建對象。
靜態方法在訪問本類的成員時,只允許訪問靜態成員(即靜態成員變量和靜態方法),而不允許訪問實例成員變量和實例方法;實例方法則無此限制。
九. 構造方法
9.1、特性
- 名字與類名相同;
- 沒有返回值。但是不能用void聲明構造函數(方法);
- 生成類的對象時自動執行,無需調用。
9.2、構造方法是否可以被override
在繼承中我們就知道父類的私有屬性和構造方法不能被繼承,所以Constructor也就不能被override(重寫),但是可以overload(重裝),所以你可以看到一個類中有多個構造函數的情況。
9.3、父子關系的構造方法的執行順序
- 父類有無參構造方法,子類才可以寫無參構造方法;父類有含參構造方法,子類才可以寫含參構造方法。
- 構造方法不能被繼承、重寫。
- 當進行無參構造時,先調用父類無參構造方法,然后調用子類無參構造方法;當進行有參構造時,先調用父類有參構造,然后調用子類有參構造。
十. this和super關鍵字
- super關鍵字用于從子類訪問父類的變量和方法,也包含構造方法。
- this關鍵字用于引用類的當前實例。此關鍵字是可選的。這意味著如果上面的實例在不使用此關鍵字的情況下表現相同。但是,使用此關鍵字可能會使代碼更易讀或易懂。this也可以調用當前類的構造方法。
- super調用父類中的其他構造方法時,調用時要放在構造方法的首行!this調用本類中的其他構造方法時,也要放在首行。
- this、super不能用在靜態方法中。因為被static修飾的成員屬于類,不屬于單個這個類的某個對象,被類中所有對象共享。而this代表對本類對象的引用,指向本類對象;而super代表對父類對象的引用,指向父類對象;所以,this和super是屬于對象范疇的東西,而靜態方法是屬于類范疇的東西。
十一. 重載和重寫的區別
- 重載:發生在同一個類中,方法名必須相同,參數類型不同,個數不同,順序不同,方法返回值和訪問修飾符可以不同,發生在編譯時。
- 重寫:發生在子父類中,方法名、參數列表必須相同,返回值范圍小于等于父類,拋出的異常范圍小于等于父類,訪問修飾符范圍大于等于父類;如果父類方法訪問修飾符為private則子類就不能重寫該方法。
十二. String和StringBuffer、StringBuidler
12.1 可變性
String類中使用final關鍵字修飾的字符數組保存字符串private final char value[],所以String對象是不可變的。
而StringBuidler與StringBuffer都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符串數組保存字符串 char value[] 但是由于沒有用final關鍵字修飾,所以這兩個類都是可變的。
12.2 線程安全性
- String中的對象是不可變的,也就是可以理解為常量,線程安全。
- AbstractStringBuilder 是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
- StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。
- StringBuilder并沒有對方法進行加同步鎖,所以是非線程安全的。
12.3 性能
每次對String類型進行改變的時候,都會生成一個新的String對象,然后將地址引用指向新的String對象。
StringBuffer每次都會對StringBuffer對象本身進行操作,而不是生成新的對象并改變對象引用。相同情況下使用StingBuilder相比使用StringBuffer僅能獲得10%~15%左右的性能提升,但卻要冒著多線程不安全的風險。
12.4 對于三者的使用總結
- 操作少量的數據:String
- 單線程在字符串緩沖區下操作大量數據:StringBuidler
- 多線程在字符串緩沖區下操作大量數據:StringBuffer
十三. 自動裝箱與拆箱
- 裝箱:將基本類型用它們對應的引用類型包裝起來;
- 拆箱:將包裝類型轉換為對應的基本數據類型;
十四. HashCode、equals與==
14.1 HashCode()介紹
hashcode()的作用是獲取哈希碼,也成為散列碼。它實際上返回的是一個int類型的整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashcode()定義在JDK的Object類中,這就意味著Java中任何類都包含有hashcode()函數。另外需要注意的是:Object的hashcode方法是本地方法,也就是用c或c++實現的,該方法通常用來將對象在內存中的內存地址轉換為整數之后返回。
14.2 為什么需要hashCode
以"HashSet如何保證唯一"為例子來說明為什么要有hashcode:
當你把對象加入HashSet時,jvm會先去檢索HashCode方法,如果返回值是相等的,進而調用equals方法比較內容,如果內容(各種字段值)相同,那么返回true,數據就不往里面添加,因為里面已經存有該實例,如果返回是false就說明,是不同的實例對象,就往里面存。
因此,保證每個類的HashCode的值的唯一性,有助于提高效率,這也就是下面第三條約定所談及的內容,因為,一旦判斷出來hashcode不同,就相當于不用比較equals里面的字段,直接存入即可。因此提高了效率。
14.3 hashCode()與equals()的相關規定
- 如果兩個對象相等,則hashcode一定也是相同的。
- 兩個對象相等,對兩個對象分別調用equals方法都返回true。
- 兩個對象有相同的hashcode值,它們也不一定是相等的。
- 因此,equals方法被重寫過,則hashcode方法也必須被重寫。
- hashcode()的默認行為是對堆內存上的對象產生獨特值。如果沒有重寫hashcode(),則該class的兩個對象無論如何都不會相等(即使這兩個對象指向相同的數據)。
14.4 為什么兩個對象有相同的hashCode值,它們也不一定相等的?
hashCode() 所使用的雜湊算法也許剛好會讓多個對象傳回相同的雜湊值。越糟糕的雜湊算法越容易碰撞,但這也與數據值域分布的特性有關(所謂碰撞也就是指的是不同的對象得到相同的hashCode)。在HashSet中,在作對比的時候,同樣的hashCode有多個對象,它會使用equals()來判斷是否真的相同。也就是說hashCode只是用來縮小查找成本的。
14.5 ==與euqals
==:它的作用是判斷兩個對象的地址是不是相等。即:判斷兩個對象是不是同一個對象。(基本數據類型""比較的是值,引用數據類型""比較的是內存地址)
equals():它的作用也是判斷兩個對象是否相等。但它一般有兩種使用情況:
- 類沒有重寫equals()方法。則通過equals()比較該類的兩個對象時,等價于通過“==”比較這兩個對象。
- 類重寫了equals()方法。一般,我們都通過重寫equals()方法來比較兩個對象的內容是否相等;如果內容相等,則返回true(即,認為這兩個對象相等)。
說明:
- String中的equals方法是被重寫過的,因為Object類的equals方法是比較的對象的內存地址,而String的equals方法比較的是對象的值。
- 當創建String類型的對象時,虛擬機會在常量池中查找有沒有已經存在的值和要創建的值相同的對象,如果有就把它賦給當前引用。如果沒有就在常量池中重寫創建一個String對象。
十五. 關于final關鍵字的一些總結
final關鍵字主要用在三個地方:變量、方法、類。
對于一個final變量:
- 如果是基本數據類型的變量,則其數組一旦初始化以后就不能更改;
- 如果是引用類型的變量,則在對其初始化之后便不能再讓其指向另一個對象。
當用final修飾一個類時,表面這個類不能被繼承。final類中的所有成員方法都會被隱式的指定為final方法。
使用final修飾方法的原因:
- 把方法鎖定,以防任何繼承類修改它的含義
- 效率:在早期的Java實現版本中,會將final方法轉為內嵌調用。但是如果方法過于龐大,可能看不到內嵌調用帶來的任何性能提升(現在的Java版本已經不需要使用final方法進行這些優化了)。類中所有的private方法都隱式地指定為final。
十六. 接口和抽象類的區別
- 接口的方法默認是public,所有的方法在接口中不能有實現(Java8開始接口方法可以有默認實現),抽象類可以有非抽象的方法。
- 接口中的實例變量默認是final類型的,而抽象類中則不一定。
- 一個類可以實現多個接口,但最多只能實現一個抽象類。
- 一個類實現接口的話要實現接口中的所有方法,而抽象類不一定。
- 接口不能用new 實例化,但可以聲明,但是必須引用一個實現該接口的對象;從設計層面來說,抽象是對類的抽象,是一種模板設計,接口是行為的抽象,是一種行為的規范。
備注:在JDK8中,接口也可以定義靜態方法,可以直接用接口名調用。實現類和實現是不可以調用的。如果同時實現兩個接口,接口中定義了一樣的默認方法,必須重寫,不然會報錯。
十七. static關鍵字
17.1 修飾成員變量和成員方法
被static修飾的成員變量屬于靜態成員變量,靜態變量存放在Java內存區域的方法區中。
調用格式:類名.靜態變量名
被static修飾的成員方法屬于類,不屬于這個類的某個對象,被類中所有的對象共享,并且建議通過類名調用。
調用格式:類名.靜態方法名()
17.2 靜態代碼塊
靜態代碼塊定義在類中方法外,靜態代碼塊在非靜態代碼塊之間執行(靜態代碼塊-->非靜態代碼塊-->構造方法)。該類不管創建多少對象,靜態代碼塊只執行一次。
靜態代碼塊的格式是:static{語句體;}
一個類中的靜態代碼塊可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果靜態代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。
靜態代碼塊對于定義在它之后的靜態變量,可以賦值,但是不能訪問。
靜態代碼塊定義在類中方法外,靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊-->非靜態代碼塊-->構造方法)。
該類不管創建多少對象,靜態代碼塊只執行一次。
17.3 靜態內部類(static修飾類的話,只能修飾內部類)
? 靜態內部類與非靜態內部類之間存在一個巨大的區別:非靜態內部類在編譯完成之后會隱含地保存著一個引用,該引用是指向創建它的外圍類,但是靜態內部類卻沒有。沒有這個引用就意味著:
- 它的創建是不需要依賴外圍類的創建。
- 它不能使用任何外圍類的非static成員變量和方法。
17.4 靜態導包(用來導入類中的靜態資源,1.5之后的新特性)
格式為:import static
這兩個關鍵字連用可以指定導入某個類中的指定靜態資源,并且不需要使用類名調用類中靜態成員,可以直接使用類中靜態成員變量和成員方法。
17.5 靜態方法和非靜態方法
靜態方法屬于類本身,非靜態方法屬于從該類生成的每個對象。如果你的方法執行的操作不依賴于其類的各個變量和方法,請將其設置為靜態(這將使程序的占用空間更小)。否則,它應該是非靜態的。
總結:
- 在外部調用靜態方法時,可以使用“類名.方法名”的方式,也可以使用“對象名.方法名”的方式。而實例(非靜態)方法只有后面這種方式。也就是說,調用靜態方法可以無需創建對象。
- 靜態方法在訪問本類的成員時,只允許訪問靜態成員(即靜態成員變量和靜態方法),而不允許訪問實例成員變量和實例方法;實例(非靜態)方法則沒有這個限制。
17.6 靜態代碼塊和非靜態代碼塊
- 相同點:都是在JVM加載類時且在構造方法執行之前執行,在類中都可以定義多個,定義多個時按定義的順序執行,一般在代碼塊中對一些static變量進行賦值。
- 不同點:靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊->非靜態代碼塊->構造方法)。靜態代碼塊只在第一次new 的時候執行一次,之后不再執行,而非靜態代碼塊每new一次就執行一次。非靜態代碼塊可在普通方法中定義(不過作用不大);而靜態代碼塊不行。
一般情況下,如果有些代碼,比如一些項目最常用的變量或對象必須在項目啟動的時就執行的時候,需要使用靜態代碼塊,這種代碼是主動執行的。如果我們想要設計不需要創建對象就可以調用類中的方法,例如:Arrays類,Character類,String類等,就需要使用靜態方法,兩者的區別是:靜態代碼塊是自動執行的而靜態方法是被調用的時候才執行的。
17.7 非靜態代碼塊和構造函數
- 非靜態代碼塊與構造函數的區別是:
- 非靜態代碼塊是給所有對象進行統一初始化,而構造函數是給對應的對象初始化。
因為構造函數是可以多個的,運行哪個構造函數就會建立什么樣的對象,但無論建立哪個對象,都會先執行相同的構造代碼塊。也就是說,構造代碼塊中定義的是不同對象共性的初始化的內容。
17.8 在一個靜態方法內調用一個非靜態成員為什么是非法的
由于靜態方法可以不通過對象進行調用,因此在靜態方法里,不能調用其他非靜態變量,也不可以訪問非靜態變量成員。
Java程序員福利:我把2019近一年經歷過的Java崗位面試,和一些刷過的面試題都做成了PDF,PDF都是可以免費分享給大家的,關注私信我:【101】,免費領取!
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的java匿名对象赋初值_不想进BAT的Java程序员不是好程序员,BAT后端Java岗面试真题分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows出现不是正版怎么解决办法
- 下一篇: 空调外机会不会从房顶掉落啊?