Java 內部類詳解


Java 內部類詳解

內部類

內部定義普通類、抽象類、接口的統稱,是指一種嵌套的結構關係。

缺點:破壞了良好的程序結構。

優點:內部類定義在類的內部,可以方便訪問外部類的的私有成員,並且和其它類進行隔離,每個內部類都能獨立的繼承一個接口的實現,所以無論外部類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。

成員內部類-外部類訪問內部類私有成員

成員內部類是依託外部類而存在的,定義在類內部的非靜態類,就是成員內部類。代碼示例如下:

<code> package neibu;
 class Outer{
     private int age ;
     private int name ;  
  public Outer() {
  super();
  // TODO Auto-generated constructor stub
  }
 
  public Outer(int age) {
  super();
  this.age = age;
  }
 
  public Intter getInfo() {
  Intter inter = new Intter("guoqun");

  return inter ;
  }
 
  class Intter{
  private String name ;
 
 
  public Intter(String name) {
  super();
  this.name = name;
  }
 
  public void name() {
              /*Intter類 像是Outer類的一個成員,Outer稱為外部類。
成員內部類可以無條件訪問外部類的所有成員屬性和成員方法,
包括private成員和靜態成員。*/
  System.out.println(Outer.this.age + this.name);
 
  }
  }
 }/<code>

Intter類是Outer類的一個內部類,Outer稱為外部類。成員內部類可以無條件訪問外部類的所有成員屬性和成員方法,包括private成員和靜態成員。

需要注意的是,雖然成員內部類可以無限制的訪問外部類中成員或方法,但當成員內部類與外部類擁有同名成員變量或者方法時,會發生覆蓋,即默認情況下訪問的是成員內部類的成員,如上述代碼示例的name成員變量。如果要訪問外部類的同名成員,需要以下面的形式進行訪問:

<code> 外部類.this.成員變量 ,如Outer.this.age 

 外部類.this.成員方法/<code>

外部類訪問成員內部類的成員,需要先創建一個成員內部類的對象,再通過引用來訪問內部類成員。

內部類可以直接被實例化,語法格式:

<code> 外部類.內部類 對象名稱 = new 外部類().new 內部類();/<code>

代碼示例如下:

<code> public class Lian {
 
  public static void main(String[] args) {
  // TODO Auto-generated method stub
  Outer.Intter inttera = new Outer(10).new Intter("guoqun");
  inttera.name();
    }
 }/<code>

內部類可以擁有private訪問權限、protected訪問權限、public訪問權限及包訪問權限。內部類私有化,可以使用 private、protected實現。如上面示例中,如果成員內部類Intter使用private進行修飾,那麼只能在外部類的內部訪問;如果用protected進行修飾,那麼只能在同一個包下或繼承外部類時訪問;如果使用public進行修飾,那麼在任何地方都能訪問;如果是默認訪問權限(default),則只能在同一個包下訪問。這一點和外部類有一點不一樣,外部類只能被public或default訪問權限修飾。


定義內部接口

<code> package neibu;
 
 interface Jiekou{
 
  public abstract void jie(T x);
  // 內部接口
  interface KouJie {
  public abstract void fun();
 
  }
 
 ​
 class Jj implements Jiekou{
  public void jie(T x) {
  System.out.print(x);
  }
 
  class Abs implements KouJie {
  public  void fun() {
  System.out.print("asdasda");
 ​
  }
  }
 
 }
/<code>

實例化內部類接口實例化對象前需要首先獲取外部類實例化對象,代碼示例如下:

<code> public class Lian {
 
  public static void main(String[] args) {
         // 實例化外部類接口對象
  neibu.Jiekou<integer> Jie = new neibu.Jj<integer> () ;
  Jie.jie(10 );
         // 實例化內部類接口實例化對象前需要首先獲取外部類實例化對象

  Jiekou.KouJie kou = ((Jj) Jie).new Abs();
  kou.fun();
    }
 ​
 }/<integer>/<integer>/<code>


接口子類定義為自身內部類

<code> package neibu;
 public class Lian {
 
  public static void main(String[] args) {
 
  FaceM.getFace().getInfo();
  }
 
 }
 interface FaceM{
  public abstract void getInfo();
  class mm implements FaceM {
  public void getInfo() {
  System.out.println("接口子類定義為自身內部類");
  }
  }
  public static FaceM getFace() {
  return new mm();
  }
 }/<code>


static 定義內部類(靜態內部類)

使用static定義內部類,此時的內部類不再受外部類實例化對象的影響,所以等同於於一個“外部類”,內部類的名稱為“外部類.內部類”,同時static定義的內部類只能調用外部類中static定義的結構,並且在進行內部類的實例化時也不再需要先獲取外部類實例化對象,static內部類對象實例化格式如下:

外部類內部類內部類對象外部類內部類

<code> package neibu;
 public class Lian {
 
  public static void main(String[] args) {
  // TODO Auto-generated method stub
  System.out.println();
  Outer.Intter inttera = new Outer.Intter("guoqun");
  inttera.name();
  }
 }
 class Outer{
  public Outer(int age) {
  super();
  this.age = age;
  }
 
  public Intter getInfo() {
  Intter inter = new Intter("guoqun");
  return inter ;
  }
 
  private int age ;
  static class Intter{
  private String name ;
  public Intter(String name) {
  super();
  this.name = name;
  }
 
  public void name() {
  System.out.println(this.name);
 
  }
  }
 }/<code>

使用static 定義內部接口(靜態內部類)

<code> package neibu;
 public class Lian {
 
  public static void main(String[] args) {
  // TODO Auto-generated method stub
  System.out.println();

  JieKou.Load load = new LoadFace();
  JieKou.Compare compare = new CompareFace();
  JieKou.getInfo(load, compare);
  }
 
 }
 
 interface JieKou{
  // 內部接口
  static interface Load {
  public abstract boolean loadData();
  }
     
  static interface Compare {
  public abstract void compareData();
  }
     
  public static void getInfo(Load sLoad , Compare sCompare) {
  if (sLoad.loadData()) {
  Compare.compareData();
  }
  else {
  System.out.println("加載失敗");
  }
  }
 }
 
 class LoadFace implements JieKou.Load{
  public boolean loadData() {
  return true;
  }
 }
 
 class CompareFace implements JieKou.Compare{
  public void  compareData() {
  System.out.println("compareData");
  }
 }
 /<code>

方法中定義內部類(局部類)

<code> package neibu;
 
 public class Lian {
 
  public static void main(String[] args) {
  // TODO Auto-generated method stub

  System.out.println();
  Outer outer = new Outer(12);
  outer.getInfo();
  }
 
 }
 
 
 class Outer{
  private int  age ;
  public Outer(int age ) {
  this.age = age ;
  }
  public void   getInfo() {
  class Inter {  // 內部類
  public void interFun() {
  System.out.println("interFun" + Outer.this.age) ;
  }
  }
  new Inter().interFun() ;
 
  }
 }/<code>

如果一個類只在某個方法中使用,則可以考慮使用局部類。

匿名內部類,函數式接口

匿名內部類使用廣泛,如我們常用的綁定監聽的時候。

<code> package neibu;
 public class Lian {
  public static void main(String[] args) {
         /*
         接口對象無法直接實例化,使用匿名內部類後就可以利用對象的實例化格式獲取接口實例
         */
  Face face  = new Face() { // 匿名內部類
  @Override
  public void name() {
  // TODO Auto-generated method stub

  System.out.println("sss");
  }
  };
  }
 
 }
 
 @FunctionalInterface
 interface Face {
  public abstract void name();
 
 }/<code>

在接口中利用匿名內部類實現接口

<code> package neibu;
 public class Lian {
  public static void main(String[] args) {
  FaceN.getFace().name();
  }
 
 }
 interface FaceN {
  public abstract void name();
  public static FaceN getFace() {
  return new FaceN() {
  @Override
  public void name() {
  System.out.println("在接口中利用匿名內部類實現接口");
 
  }
  };
  }
 
 }/<code>

適合於接口只有一個子類的時候,並且也可以對外部調用處隱含子類。


分享到:


相關文章: