怎么使用Java内部类

发布时间:2021-10-28 10:59:29 作者:iii
来源:亿速云 阅读:149

这篇文章主要介绍“怎么使用Java内部类”,在日常操作中,相信很多人在怎么使用Java内部类问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用Java内部类”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、内部类如何创建

内部类,顾名思义就是类中类,将类定义在外围类里面:

public class Animal {      class Monkey{         private String name = "monkey";          public String getName() {             return name;         }     }      class Pig {         private String color;          Pig(String color) {             this.color = color;         }          String getColor() {             return color;         }     }      public void getAnimal(String note) {         Monkey monkey = new Monkey();         Pig pig = new Pig(note);         System.out.println(pig.getColor());     }      public static void main(String[] args) {         Animal animal = new Animal();         animal.getAnimal("pink");     } } /* OUTPIT: pink */

因为Monkey和Pig两个类是定义在 Animal 类中,因此使用起这两个内部类跟使用普通类没什么区别。下面这组代码相信小伙伴也不陌生:

public class Animal {      class Monkey{     }      class Pig {     }      public Monkey getMonkey() {         return new Monkey();     }      public Pig getPig() {         return new Pig();     }      public static void main(String[] args) {         Animal animal = new Animal();         Animal.Monkey monkey = animal.getMonkey();         Animal.Pig pig = animal.getPig();     } }

通过定义方法,来返回执行内部类的引用。不知道细心的小伙伴有没有注意到内部类的引用有点奇怪:Animal.Monkey。这也是内部类的区别之一,如果要在外部类的非静态方法之外获取某个内部类的对象,需要「具体指明这个对象的类型」:OuterClassName.InnerClassName

二、内外相连

内部类存在于外部类里层,因此也具有一定特权:内部类可以访问外围对象的所有成员,不需要任何特殊条件,此外,内部类还拥有外部类的所有元素的访问权。

public class OuterArray {     private Integer[] ints;     private int next = 0;      public OuterArray(int size) {         ints = new Integer[size];     }      public void add(int x) {         if (next < ints.length) {             ints[next++] = x;         }     }      class InnerArray {         private int i = 0;          public boolean end() {             return i == ints.length;         }          public int current() {             return ints[i];         }          public void next() {             if (i < ints.length) {                 i++;             }         }     }      public static void main(String[] args) {         OuterArray outerArray = new OuterArray(10);         for (int i = 0; i < 10; i++) {             outerArray.add(i);         }         InnerArray innerArray = outerArray.new InnerArray();         while (!innerArray.end()) {             System.out.print(innerArray.current()+" ");             innerArray.next();         }     } }

上组代码中我们可以看到,InnerArray可以访问到OuterArray中的每一个属性,就像自己拥有它们一样,这带来了很大的方便。

三、new 和 this

这两个关键字我们肯定都不陌生了,我们平时用到最多的肯定就是new一个对象出来。

public class OuterClass {      class InnerClass {     }      public static void main(String[] args) {         OuterClass outer = new OuterClass();     } }

当我们需要OuterClass对象的时候,我们顺手就来了个new  OuterClass(),但是如果我们需要的是InnerClass对象,那么又该如何处理呢?答案便是:

InnerClass inner = outer.new InnerClass();

可能觉得有点奇怪,为什么此处的new需要以OuterClass对象引用,这是因为内部类对象会暗暗地连接到创建它的外部类对象上,因此必须使用外部类的对象来创建内部类对象。如果你创建的是「嵌套类」(静态内部类),那么它就不需要对外部类对象的引用。

this关键字是用来生成对外部类对象的引用,这样产生的引用自动具有正确的类型:

public class OuterClass {      class InnerClass {         public OuterClass getOuterClass() {             return OuterClass.this;         }     }      public static void main(String[] args) {         OuterClass outer = new OuterClass();         InnerClass inner = outer.new InnerClass();         OuterClass outerClass = inner.getOuterClass();     } }

四、局部内部类

我们上面看到的内部类都是定义在外部类中,这也是内部类的典型用处。但是,我们也可以在一个方法里面或者任意的作用域里面定义内部类。这种也被称为局部内部类:

public class OuterClass {      public Animal getPig(String color) {         class Pig extends Animal {             @Override             public void getAnimal(String color) {                 super.getAnimal(color);             }         }         return new Pig();     }      public static void main(String[] args) {         OuterClass outerClass = new OuterClass();         Animal pink = outerClass.getPig("pink");     } }

Pig类是getPig()方法的一部分,而不是OuterClass的一部分,所以在getPig()之外不能访问Pig类。

五、匿名内部类

在了解什么是匿名内部类之前,我们先看一组代码:

public class OuterClass {      public Animal animal() {         return new Animal(){             private String name = "monkey";             @Override             public String toString() {                 return "animal{" +                         "name='" + name + '\'' +                         '}';             }         };     }      public static void main(String[] args) {         OuterClass outerClass = new OuterClass();         System.out.println(outerClass.animal());     } } /* OUTPUT: animal{name='monkey'} */

animal()这个方法将返回值的生成与表示这个返回值的类定义结合在一起。而且这个类是匿名的,它没有名字,正常形式应该是这样的:

public class OuterClass {      class Monkey extends Animal {         private String name = "monkey";          @Override         public String toString() {             return "animal{" +                     "name='" + name + '\'' +                     '}';         }     }          public Animal animal() {         return new Monkey();     } }

匿名类再访工厂:

public interface Service {     void method1(); } interface ServiceFactory{     Service getService(); }  class Implementation1 implements Service {      private Implementation1(){}      @Override     public void method1() {         System.out.println("Implementation1.method1()");     }      public static ServiceFactory factory = new ServiceFactory() {         @Override         public Service getService() {             return new Implementation1();         }     }; }  class Factories{     public static void main(String[] args) {         ServiceFactory factory = Implementation1.factory;         Service service = factory.getService();         service.method1();     } }

通过内部类获取外部类的实现,这样子Implementation1的构造器都可以是private的,并且没有任何必要去创建作为工厂的具体类,这样所产生的语法也更具有实际意义,也可以运用在单例模式中。

六、嵌套类

如果不需要内部类对象与外围类之间有联系,就可以将内部类声明为static,这通常称为嵌套类。普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象,然而,当内部类是static的时候,就意味着:

要创建嵌套类的对象,并不需要其外围类的对象

不能从嵌套类的对象中访问非静态的外围类对象

public class NestClass {          static class InnerNestClass{     }      public static InnerNestClass get() {         return new InnerNestClass();     }      public static void main(String[] args) {         InnerNestClass innerNestClass = get();     } }

在main()方法中没有任何NestClass对象是必须的,而是使用选取static成员的普通语法来调用方法。

接口内部类

正常情况下,不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分。你放到接口中的任何类都自动是public和static的。因为类是static的,只是将嵌套类置于接口的命名空间内,这并不违反接口的规则。你甚至可以在内部类中实现其外部类的接口:

public interface ClassInterface {      void test();      class Test implements ClassInterface {          @Override         public void test() {             System.out.println("接口中的嵌套类");         }          public static void main(String[] args) {             new Test().test();         }     } }

如果你想要的创建某些公共代码,使得它们可以被某个接口的所有不同实现所共用,那么使用接口内部的嵌套类会显得很方便,尽管在 Java 8 之后可以使用  default 来默认实现接口方法。

七、继承内部类

内部类作为一种类,被继承当然也是被允许的。但是因为内部类的构造器必须连接到指向其外围类对象的引用,所以在继承内部类的时候,那个指向外围类对象的引用必须被初始化,而在导出类中不再存在可连接的默认对象

可以看到,通过这样继承是会报错的,解决方法便是:

class ExtendClass {     class Inner{} }  class WithInner extends ExtendClass.Inner {     public WithInner(ExtendClass extendClass) {         extendClass.super();     } }

因此我们需要记住,如果要继承一个内部类的时候,必须在构造器内使用外部类.super(),这样才能提供了必要的引用,然后程序才能编译通过。

八、覆盖内部类?

当子类继承父类时,子类可以覆盖父类的方法。那么问题来了,内部类能否被覆盖?我们通过看一组代码来找找答案:

public class Flower {      class Bud{         public Bud(){             System.out.println("Flower.Bud");         }     }      public Flower(){         System.out.println("new Flower()");         new Bud();         test();     }      public void test() {         System.out.println("Flower.test()");     } }  class Flower2 extends Flower{      class Bud{         public Bud(){             System.out.println("Flower2.Bud");         }     }     public void test() {         System.out.println("Flower2.test()");     }      public static void main(String[] args) {         new Flower2();     } } /* OUTPUT new Flower() Flower.Bud Flower2.test() */

从这个例子中我们可以看到,当继承了某个外围类的时候,内部类并没有发生什么特别神奇的变化,这两个内部类是完全独立的两个实体,各自在自己的命名空间内。

九、为什么要使用内部类?

我们在回答这个问题之前先明白一件事情:

「每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响」

这句话很清楚的说明了内部类的能力,如果没有内部类提供的、可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决,从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,为内部类有效地实现了"多重继承"。

到此,关于“怎么使用Java内部类”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. Java内部类的实现
  2. Java内部类

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:如何进行ASP.NET AJAX组成部分的解析

下一篇:Mysql数据分组排名实现的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》