1. 程式人生 > >Java 內部類詳解及其練習

Java 內部類詳解及其練習

學習心得

一、專業課

1內部類

1.內部類

1.1 是指在一個外部類的內部再定義一個類,類名不需要和夾相同

1.2部類可以是靜態static的,也可publicdefaultprotectedprivate修飾(而外部類只能使用 publicdefault

1.3注意:內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩類。對於一個名為outer的外部類和其內部定義的名為 inner的內部類。編譯完成後出現outer.class outer$inner.class兩類。所以內部類的成員變數/方法名可以和外部類的相同

2成員內部類

成員內部類,就是作為外部類的成員,可以直接使用外部類的所有成員和方法,即使是

private 的。同時外部類要訪問內部類的所有成員變數/方法,則需要通過內部類的物件來獲取

3.區域性內部類

區域性內部類,是指內部類定義在方法和作用域內

4.匿名內部類沒有引用名的內部類

publicclass InnerClass {

publicstatic void main(String[] args) {

/*

* 1.內部類

* 1.1 是指在一個外部類的內部再定義一個類,類名不需要和文件夾相同

* 1.2 內部類可以是靜態static的,也可用 publicdefaultprotectedprivate修飾

* (而外部類只能使用publicdefault

* 1.3

注意:內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩類。

* 對於一個名為outer的外部類和其內部定義的名為 inner的內部類。

* 編譯完成後出現outer.classouter$inner.class兩類。所以內部類的成員變數/方法名可以和外部類的相同。

*/

Bodybody = new Body();

Body.Heartheart = new Body().new Heart(); //非靜態內部類時的宣告方式

// Body.Heartheart2 = new Body.Heart(); // 注意靜態內部類的生成(不需要Body後的())

heart.thump();

body.walk();

Sleepsleep = new Sleep();

sleep.sleep("yes",new YesOrNo() { //匿名內部類

@Override

publicvoid no() {

//TODO Auto-generated method stub

System.out.println("no,最多再睡三分鐘");

}

@Override

publicvoid yes() {

//TODO Auto-generated method stub

System.out.println("yes,多睡六分鐘");

}

});

}

}

classBody{

staticprivate int weigth;

publicvoid walk() {

inti = 2;

System.out.println("walk");

classShoes{ //成員方法中,成員內部類,只能用 default(不能寫出)finali一樣

publicvoid wear() {

System.out.println("blackshoes"+i); //jdk1.8開始i才不需要是final常量

}

}

//區域性內部類相當於一個屬性,需要在內部初始化,外部無法呼叫

newShoes().wear();

}

publicstatic void sWalk() {

System.out.println("staticwalk");

}

/*

* 成員內部類,就是作為外部類的成員,可以直接使用外部類的所有成員和方法,即使是private的。

* 同時外部類要訪問內部類的所有成員變數/方法,則需要通過內部類的物件來獲取

*/

/*static*/class Heart{ //成員位置上的內部類,成員內部類(可以static

intrate;

/*

* 成員內部類(非靜態)不能含有static的變數和方法。因為成員內部類需要先建立了外部類,才能建立它自己的

* 靜態變數需要在一個靜態環境中,也就是內部類需要時靜態的

*/

// staticint r;

/**

* java類載入順序,首先載入類,執行static變數初始化,接下來執行物件的建立,如果我們要執行程式碼中的變數intr 初始化,

* 那麼必須先執行載入外部類,再載入內部類,最後初始化靜態變數a,問題就出在載入內部類上面,

* 不妨把內部類看成外部類的非靜態成員,它的初始化必須在外部類物件建立後以後進行,要載入內部類必須在例項化外部類之後完成,

* java虛擬機器要求所有的靜態變數必須在物件建立之前完成,這樣便產生了矛盾

* java常量放在記憶體中常量池,它的機制與變數是不同的,編譯時,載入常量是不需要載入類的,所以就沒有上訴那種矛盾

*/

staticfinal int r = 2;

publicvoid thump() {

System.out.println("heartthumping");

System.out.println(weigth+Body.this.weigth);//問外部類屬性可以用外部類.this.屬性名來呼叫

sWalk();

walk();

classT{} //厲害了,居然還可以巢狀,但還是饒了別人把

}

}

}

classSleep{

classHeart{} //不同類下可以有重名的內部類

publicvoid sleep(String or,YesOrNo yesOrNo) {

if("yes".equals(or)) {

yesOrNo.yes();

}else{

yesOrNo.no();

}

}

interfaceYesOrNo{

voidyes();

voidno();

}

}

二、小組PK

1.我方題目

1.以下程式能否執行

如果不能請指出錯在那裡,

如果可以請輸出程式結果:

classB extends A {

publicB() {

System.out.println("B");

}

publicvoid show(B obj) {System.out.println("B and B"); }

publicvoid show(A obj) {System.out.println("B and A");}

}

classC extends B {

Dd = new D();

classD {

D(){

show(newA());

}

}

}

publicclass A {

publicvoid show(A obj) {System.out.println("A and A");}

publicstatic void main(String[] args) {

Cc = new C();

c.show(newB());

}

}

B //建立C的例項,呼叫C的無參構造方法,C的預設構造方法第一條語句隱含它的父類B的無參構造方法,所以第一個輸出B

Band A //D()呼叫show(newA())newA()是陷阱,因為並沒有呼叫Ashow方法。所以是呼叫Dshow()方法。

//D及它的外部類C中都沒有定義show方法,所以找到C的父類B中,根據引數對應輸出B and A

B //c.show(newB()),呼叫publicB(),輸出B

Band B //根據引數找到 Band B

2.請找出下面程式的錯誤,可能有幾處(請在錯誤語句後面打星*):

publicclass Animal {

classAnima{

System.out.println("animal"); *//輸出語句不能寫在這個位置,應該寫在方法或者語句塊中

}

publicstatic void main(String[] args) {

Integeri = -2;

Catcat = new Animal(); *//向下轉型需要將強制型別轉換

Animaldog = new Dog();

if(cat instanceof Dog) { *//eclipse編譯器會報編譯錯誤

System.out.println("cat");

}

}

}

classCat extends Animal{}

classDog extends Animal{}

3.請找出下面程式的錯誤,可能有幾處(請在錯誤語句後面打星*):

publicclass Test {

inta;

voidTest(int a){ //這不是建構函式

this.a=a++;

}

publicstatic void main(String[] args) {

finalTest t = new Test(5);* //沒有帶參的建構函式

}

privateclass A{

Staticint a = 10; *//Static 這個不是靜態關鍵字

System.out.println(a); *

public void getA(final Test t){

t= new Test(6); *

System.out.println(t.a);

}

}

}

4.程式是否能夠執行,如果能執行結果是什麼?不能請說明理由

注意輸出格式

publicclass Question {

publicstatic void main(String[] args) {

Aa = new B();

System.out.println(a.method1('c'));

a.fun(); ***

}

}

classA{

staticint i;

inta = 10;

{

i= method1('d');

}

public int method1(char c){

if(c> 0){

returni + a;

}

return0;

}

staticvoid method(){

i++;

}

}

classB extends A{

public void fun(){

System.out.println(i);

A.method();

}

}

程式不能執行,在帶*出物件a不能呼叫fun()方法,因為父類A裡面沒有fun方法,所以A類的引用找不到fun方法,報錯。

5.分別用惡漢式和 懶漢式 實現單例設計模式 intage 方法名自擬

classSingle{

privateint age;

privateSingle() {

super();

}

publicint getAge() {

returnage;

}

publicvoid setAge(int age) {

this.age= age;

}

privatestatic Single s = new Single();

publicstatic Single getInstances(){

returns;

}

}

classSingle2{

privateint age;

privateSingle2() {

super();

}

publicint getAge() {

returnage;

}

publicvoid setAge(int age) {

this.age= age;

}

privatestatic Single2 s = null;

publicsynchronized static Single2 getInstances(){

if(s== null){

s= new Single2();

}

returns;

}

}

2、對方題目

1publicclass Demo03 extends S{

publicfinal void mb_method(int i){

System.out.println(i);

}

publicstatic void main(String[] args) {

//TODO Auto-generated method stub

Demo03demo01 = new Demo03();

demo01.mb_method();

demo01.mb_method(2);

}

}

classS{

publicfinal void mb_method(){

System.out.print("1");

}

}

A.程式可以通過編譯,並正常執行輸出“12”

B.程式可以通過編譯,但無法正常執行

C.程式無法通過編譯,因為方法呼叫有問題

D.程式無法通過編譯,因為具有final屬性的方法不能被覆蓋

A

2父類為Person,子類為Student,父類中有一個使用private修飾的屬性school,student的物件想要修改該屬性的值為“新東方”並且獲取該屬性打印出來,該如何實現?請完整下列程式程式。

classPerson{

privateString school;

}