內部類分別有成員內部類、局部內部類、匿名內部類、靜態內部類,接下來將分別介紹。java
public class Demo1 { innerclass in=new innerclass(); //在成員內部類所在的外類中實例化成員內部類 public void outf() { in.inf(); //由於in是成員內部類的實例化,因此才能夠調用 } class innerclass{//成員內部類 int y=0; public innerclass() {//成員內部類的構造方法 } public void inf() { System.out.println("內部類方法y="+y); } } public static void main(String[] args) { Demo1 iDemo1=new Demo1(); iDemo1.outf(); Demo1.innerclass j= iDemo1.new innerclass(); //非外部類位置成員內部類實例化的方法(即首先要實例化一個外部類) Demo1.innerclass k=new Demo1().new innerclass(); //實例化外部類和構造內部類一塊兒寫 j.inf(); } }
public class Demo2 { public outinterface action(String x) {//要把這個類返回出去,就須要經過接口,由於內部類在外部做用域中不存在 class innerclass2 implements outinterface{ public innerclass2(String s) { s = x; System.out.println(s); } } return new innerclass2("do"); } public static void main(String[] args) { Demo2 demo2=new Demo2(); demo2.action("局部內部類"); } } interface outinterface{ //專門用來給局部內部類作向上轉型的父接口的操做 }
局部內部類只能在所在的方法體做用域內進行實例化,而若是要在所在方法體返回該類,就要經過接口向上轉型的操做。(如同上處代碼)
2. 做用
在某些狀況下,某些業務邏輯須要臨時處理,這些業務邏輯只在這裏使用又能夠封裝成一個類的話,而又不必從新建個文件,因此能夠這寫一個局部內部類來處理。而後,在個人記憶中,java代理模式中有用到局部內部類,在方法中直接實現接口,返回代理對象,簡單而又方便。安全
靜態字段的內部類,和靜態方法並列。學習
public class Demo3 { static int x=100; static class innerclass3 { void action() { x=1; //x必須是靜態字段 } public static void main(String[] args) { System.out.println("我是靜態內部類"); } } }
//代碼示例一 public class Demo4 { public Outinterface2 action() { //return new innerclass2(); ① return new Outinterface2() { //② private int i = 0; public int getvalue() { return i; } }; } } interface Outinterface2 { } class innerclass2 implements Outinterface2{//① private int i = 0; public int getvalue() { return i; } }
//代碼示例二 interface Inner { public abstract void show(); } class Outer { public void method(){ new Inner() { public void show() { System.out.println("HelloWorld"); } }.show(); } } class Test { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } //若是匿名內部類中有多個方法又該如何調用呢? Inter i = new Inner() { //多態,由於new Inner(){}表明的是接口的子類對象 public void show() { System.out.println("HelloWorld"); } };
上述代碼①和②的做用是相同的。由此也能夠解釋一下匿名內部類的做用。測試
做爲一個類的編寫者,咱們很顯然須要對這個類的使用訪問者的訪問權限作出必定的限制,咱們須要將一些咱們不肯意讓別人看到的操做隱藏起來,若是咱們的內部類不想輕易被任何人訪問,能夠選擇使用private修飾內部類,這樣咱們就沒法經過建立對象的方法來訪問,想要訪問只須要在外部類中定義一個public修飾的方法,間接調用。代理
public interface Demo { void show(); } class Outer { private class test implements Demo { public void show() { System.out.println("密碼備份文件"); } } public Demo getInner() { return new test(); } }
咱們以前的學習知道,java是不能夠實現多繼承的,一次只能繼承一個類,咱們學習接口的時候,有提到能夠用接口來實現多繼承的效果,即一個接口有多個實現,可是這裏也是有一點弊端的,那就是,一旦實現一個接口就必須實現裏面的全部方法,有時候就會出現一些累贅,可是使用內部類能夠很好的解決這些問題。調試
public class Demo1 { public String name() { return "BWH_Steven"; } } public class Demo2 { public String email() { return "xxx.@163.com"; } } public class MyDemo { private class test1 extends Demo1 { public String name() { return super.name(); } } private class test2 extends Demo2 { public String email() { return super.email(); } } public String name() { return new test1().name(); } public String email() { return new test2().email(); } public static void main(String args[]) { MyDemo md = new MyDemo(); System.out.println("個人姓名:" + md.name()); System.out.println("個人郵箱:" + md.email()); } }
咱們編寫了兩個待繼承的類Demo1和Demo2,在MyDemo類中書寫了兩個內部類,test1和test2二者分別繼承了Demo1和Demo2類,這樣MyDemo中就間接的實現了多繼承。code
咱們用通俗講解就是說在Java中,一般就是編寫一個接口,而後你來實現這個接口,而後把這個接口的一個對象做以參數的形式傳到另外一個程序方法中, 而後經過接口調用你的方法,匿名內部類就能夠很好的展示了這一種回調功能。對象
public interface Demo { void demoMethod(); } public class MyDemo{ public test(Demo demo){ System.out.println("test method"); } public static void main(String[] args) { MyDemo md = new MyDemo(); //這裏咱們使用匿名內部類的方式將接口對象做爲參數傳遞到test方法中去了 md.test(new Demo){ public void demoMethod(){ System.out.println("具體實現接口") } } } }
編寫一個接口Demo繼承
public interface Demo { void test(); }
編寫一個類 MyDemo接口
public class MyDemo { public void test() { System.out.println("父類的test方法"); } }
二者的方法名字都是test,下面編寫一個測試類;
public class DemoTest extends MyDemo implements Demo { public void test() { } }
這樣的話我就有點懵了,這樣如何區分這個方法是接口的仍是繼承的,因此咱們使用內部類解決這個問題
public class DemoTest extends MyDemo { private class inner implements Demo { public void test() { System.out.println("接口的test方法"); } } public Demo getIn() { return new inner(); } public static void main(String[] args) { //調用接口而來的test()方法 DemoTest dt = new DemoTest(); Demo d = dt.getIn(); d.test(); //調用繼承而來的test()方法 dt.test(); } } //運行結果 接口的test方法 父類的test方法