內部類的訪問規則 + 內部類可以直接訪問外部類中的成員,包括私有成員。 因為內部類中持有了一個外部類的引用,格式為:外部類名.this + 外部類要訪問內部類,必須要建立內部對象。 運行結果: 訪問 1. 當內部類定義在外部類的成員位置上,而且非私有,可以在外部其他類中直接建立內部類對象。 格式: ...
內部類的訪問規則
- 內部類可以直接訪問外部類中的成員,包括私有成員。
因為內部類中持有了一個外部類的引用,格式為:外部類名.this - 外部類要訪問內部類,必須要建立內部對象。
class Outer { //外部類
private int x = 1;
class Inner{ //內部類
int x = 2;
void function() {
int x = 3;
System.out.println(x);
System.out.println(this.x);
System.out.println(Outer.this.x);
}
}
void method() {
Inner in = new Inner();
in.function();
}
}
public class InnerClassDemo {
public static void main(String[] args) {
Outer out = new Outer();
out.method();
Outer.Inner in = new Outer().new Inner();
in.function();
}
}
運行結果:
3
2
1
3
2
1
訪問
- 當內部類定義在外部類的成員位置上,而且非私有,可以在外部其他類中直接建立內部類對象。
格式: 外部類名.內部類名 變數名 = 外部類對象.內部類對象; - 當內部類在成員位置上,就可以被成員修飾符所修飾。
例如:private,將內部類在外部類中進行封裝。
static:使得內部類具有static的特性。(當內部類被static修飾後,只能直接訪問外部類中的static成員,出現了訪問的局限。)
靜態內部類
- 在外部其他類中,如何直接訪問靜態內部類的非靜態成員
class Outer {
private static int x = 1;
static class Inner {
void function() {
System.out.println(x);
}
}
}
public class InnerDemo2 {
public static void main(String[] args) {
new Outer.Inner().function();
}
}
- 在外部其他類中,如何直接訪問靜態內部類的靜態成員
class Outer {
private static int x = 1;
static class Inner {
static void function() {
System.out.println(x);
}
}
}
public class InnerDemo3 {
public static void main(String[] args) {
Outer.Inner.function();
}
}
- 當內部類中定義了靜態成員,該內部類必須也是靜態的
以下代碼編譯會導致編譯錯誤
class Outer {
private static int x = 1;
class Inner { //此內部類中定義了靜態成員但是此內部類不為靜態
static void function() {
System.out.println(x);
}
}
}
public class InnerDemo3 {
public static void main(String[] args) {
Outer.Inner.function();
}
}
- 當外部類中的靜態方法訪問內部類時,內部類也必須是靜態的。
內部類的定義原則
當描述一個事物時,這個事物的內部有事物,此時這個內部的事物需要使用內部類來描述。
局部內部類
- 內部類定義在局部時:
- 不可以被成員修飾符修飾。
- 可以直接訪問外部類中的成員,因為還持有外部類中的引用。但是不可以訪問它所在的局部變數,只能訪問被final修飾的局部變數。(目前版本的jdk中,final可以省略)
class Outer {
void method(final int x) {
class Inner {
void function() {
System.out.println(x);
}
}
new Inner().function();
}
}
public class InnerDemo4 {
public static void main(String[] args) {
Outer out = new Outer();
out.method(7);
out.method(8);//因為局部變數在棧記憶體中,每次一調用入棧,使用結束出棧。所以雖然是被final修飾,但是仍然可以重覆調用。
}
}
運行結果:
7
8
匿名內部類
- 匿名內部類其實是內部類的簡寫格式。
- 定義匿名內部類的前提:
內部類必須是繼承一個類或者實現介面。 - 匿名內部類的格式:new 父類或者介面(){定義子類的內容}
abstract class Abs {
abstract void method();
}
class Outer {
int x = 3;
/*class Inner extends Abs {
@Override
void mthod() {
System.out.println(x);
}
}*/
public void function() {
//new Inner().mthod();
new Abs() {
@Override
void method() {
System.out.println(x);
}
}.method();
}
}
public class InnerDemo5 {
public static void main(String[] args) {
new Outer().function();
}
}
運行結果
3
以上代碼將註釋部分,用匿名內部類的形式體現了出來。
- 匿名內部類是一個匿名子類對象。可以理解為帶內容的對象。
- 匿名內部類中定義的方法最好不要超過3個。
- 如果一個類既沒有實現介面也沒有繼承父類,可以使用Object類來創建匿名內部類。
例如:
public class InnerClassTest {
public static void main(String[] args) {
new Object() { //如果左邊有Object類型引用(Object ob = ),將無法調用method方法
public void method() {
System.out.println("method run");
}
}.method();
}
}
練習
interface Inter {
void method();
}
class Test {
//補足代碼,通過匿名內部類
}
public class InnerClassTest {
public static void main(String[] args) {
Test.function().method();
}
}
分析 Test.function().method(); 這行代碼可以發現function()應該是Test類中一個靜態方法,function()方法後面還有一個method()的調用,說明調用function()方法應是返回了一個對象而且是Inner類型的對象,從而才能繼續調用method()方法。
可以得到以下代碼:
interface Inter {
void method();
}
class Test {
//補足代碼,通過匿名內部類
static Inter function() { //這裡返回值類型為Inner
return new Inter(){
@Override
public void method() {
System.out.println("Hello World");
}
};
}
}
public class InnerClassTest {
public static void main(String[] args) {
Test.function().method();
}
}