java内部类

来源:互联网 发布:乐视网络电视售后电话 编辑:程序博客网 时间:2024/06/10 02:33

内部类是定义在另一个类中的类,为什么需要内部类呢?其主要原因有以下三点:

1、内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。

2、内部类可以对同一个包中的其他类隐藏起来。

3、当要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。

内部类的共性:

1、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。

2、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。

3、内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。

java内部类分为: 成员内部类、方法内部类(局部内部类)、匿名内部类、静态嵌套类 。

成员内部类:

通俗的说就是把内部类当做外部类的成员

package com.stone.InnerClassTest;import java.awt.*;import java.awt.event.*;import java.util.*;import javax.swing.*;import javax.swing.Timer;public class InnerClassTest{   public static void main(String[] args)   {      TalkingClock clock = new TalkingClock(1000, true);      clock.start();      JOptionPane.showMessageDialog(null, "Quit program?");      System.exit(0);   }}class TalkingClock{   public TalkingClock(int interval, boolean beep)   {      this.interval = interval;      this.beep = beep;   }   public void start()   {      ActionListener listener = new TimePrinter();      Timer t = new Timer(interval, listener);      t.start();   }   private int interval;   private boolean beep;   public class TimePrinter implements ActionListener   {      public void actionPerformed(ActionEvent event)      {         Date now = new Date();         System.out.println("At the tone, the time is " + now);         if (beep) Toolkit.getDefaultToolkit().beep();      }   }}

局部内部类:

把类放在方法内
class Outer {public void doSomething() {class Inner {public void seeOuter() {}}}}
(1)、局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
(2)、局部内部类对象不能使用该内部类所在方法的非final局部变量
因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。
下面是完整的例子:
package com.stone.LocalInnerClassTest;import java.awt.*;import java.awt.event.*;import java.util.*;import javax.swing.*;import javax.swing.Timer;public class LocalInnerClassTest{   public static void main(String[] args)   {      TalkingClock clock = new TalkingClock();      clock.start(1000, true);      JOptionPane.showMessageDialog(null, "Quit program?");      System.exit(0);   }}class TalkingClock{   public void start(int interval, final boolean beep)   {      final String methodname="methodname"; //不声明为final,编译报错      class TimePrinter implements ActionListener      {         public void actionPerformed(ActionEvent event)         {            Date now = new Date();            System.out.println("At the tone, the time is " + now);            System.out.println(methodname);            if (beep) Toolkit.getDefaultToolkit().beep();         }      }            ActionListener listener = new TimePrinter();      Timer t = new Timer(interval, listener);      t.start();   }}

匿名内部类

将局部内部类的使用在深入一步。假如只创建这个类的一个对象,就不必命名。这种类被称为匿名内部类顾名思义。
当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。匿名内部类的声明格式如下:
new SuperType(construction parameters){    inner class methods and data}
什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的。

1、只用到类的一个实例 。

2、类在定义后马上用到。

3、类非常小(SUN推荐是在4行代码以下)

4、给类命名并不会导致你的代码更容易被理解。

在使用匿名内部类时,要记住以下几个原则:

1、匿名内部类不能有构造方法。

2、匿名内部类不能定义任何静态成员、静态方法。

3、匿名内部类不能是public,protected,private,static。

4、只能创建匿名内部类的一个实例。

5、一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

6、因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

匿名内部类根据其实现方式的不同分为三类:继承式的匿名内部类、接口式的匿名内部类、参数式的匿名内部类。

继承式的匿名内部类:

package com.stone.AnonymousInnerClassTest;public class ExtendsAnonyInnerClass {public void drive() {System.out.println("Driving a car!");}public static void main(String[] args) {ExtendsAnonyInnerClass car = new ExtendsAnonyInnerClass() {public void drive() {System.out.println("Driving another car!");}};car.drive();}}
输出结果:
Driving another car!
接口式的匿名内部类

package com.stone.AnonymousInnerClassTest;interface Vehicle {public void drive();}public class InterfaceAnonyInnerClass {public static void main(String[] args) {Vehicle v = new Vehicle() {public void drive() {System.out.println("Driving a car!");}};v.drive();}}
输出结果:
Driving a car!
参数式的匿名内部类

package com.stone.AnonymousInnerClassTest;public class ParaAnonyInnerClass {public static void main(String[] args) {Bar b = new Bar();b.doStuff(new Foo() {public void foo() {System.out.println("foofy");}});}}class Bar {void doStuff(Foo f) {f.foo();}}interface Foo {void foo();}
我们根据以上的定时器的例子来重写一个匿名内部类实现,此实现方式为接口匿名内部类

package com.stone.AnonymousInnerClassTest;import java.awt.*;import java.awt.event.*;import java.util.*;import javax.swing.*;import javax.swing.Timer;public class AnonymousInnerClassTest {public static void main(String[] args) {TalkingClock clock = new TalkingClock();clock.start(1000, true);JOptionPane.showMessageDialog(null, "Quit program?");System.exit(0);}}class TalkingClock {public void start(int interval, final boolean beep) {ActionListener listener = new ActionListener() {public void actionPerformed(ActionEvent event) {Date now = new Date();System.out.println("At the tone, the time is " + now);if (beep)Toolkit.getDefaultToolkit().beep();}};Timer t = new Timer(interval, listener);t.start();}}

静态嵌套类

有的时候内部类只为试了把一个类隐藏在另一个类的内部,并不需要内部类引用外部类的对象。为此,可以将内部类声明为static,以便取消产生的引用。

package com.stone.StaticInnerClassTest;public class StaticInnerClassTest{   public static void main(String[] args)   {      double[] d = new double[20];      for (int i = 0; i < d.length; i++)         d[i] = 100 * Math.random();            ArrayAlg.Pair p = ArrayAlg.minmax(d);      System.out.println("min = " + p.getFirst());      System.out.println("max = " + p.getSecond());   }}class ArrayAlg{   public static class Pair   {      public Pair(double f, double s)      {         first = f;         second = s;      }      public double getFirst()      {         return first;      }      public double getSecond()      {         return second;      }      private double first;      private double second;   }   public static Pair minmax(double[] values)   {      double min = Double.MAX_VALUE;      double max = Double.MIN_VALUE;      for (double v : values)      {         if (min > v) min = v;         if (max < v) max = v;      }      return new Pair(min, max);   }}
在内部类不需要使用外围类的对象时,应该使用静态内部类。

为什么需要内部类?

典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。

使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。

0 0