java-内部类

简介: 内部类内部类既可以访问自身的数据域,也可以访问创建它的外部类对象的数据域内部类对象总有一个隐式引用,它指向了创建它的外部类的对象外部类的引用在内部类的构造方法中设置,不必手动设置,编译器会自动在构造方法中生成外部类引用只有内部类可以是私有的,建议设置为私有的,这样只有外部类的方法才可以构造该对象。在外部类的作用域中,可以通过OuterClass.InnerClass引用内部类只有静态内部类可以有静态方法import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.aw

内部类

  • 内部类既可以访问自身的数据域,也可以访问创建它的外部类对象的数据域
  • 内部类对象总有一个隐式引用,它指向了创建它的外部类的对象
  • 外部类的引用在内部类的构造方法中设置,不必手动设置,编译器会自动在构造方法中生成外部类引用
  • 只有内部类可以是私有的,建议设置为私有的,这样只有外部类的方法才可以构造该对象。
  • 在外部类的作用域中,可以通过OuterClass.InnerClass引用内部类
  • 只有静态内部类可以有静态方法

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
public class InnerClassTest
{
   public static void main(String[] args)
   {
      TalkingClock clock = new TalkingClock(1000, true);
//      使用外部类对象创建一个内部类对象
      TalkingClock.TimePrinter newClock = clock.new TimePrinter();
      newClock.print_inner();
      clock.start();
      // keep program running until user selects "Ok"
      JOptionPane.showMessageDialog(null, "Quit program?");
      System.exit(0);
   }
}
class TalkingClock
{
   private int interval;
   private boolean beep;
   public TalkingClock(int interval, boolean beep)
   {
      this.interval = interval;
      this.beep = beep;
   }
   /**
    * Starts the clock.
    */
   public void start()
   {
      ActionListener listener = new TimePrinter();
      Timer t = new Timer(interval, listener);
      t.start();
   }
   private void print() {
      System.out.println("hello");
   }
//   public void setBeep(boolean beep) {
//      this.beep = beep;
//   }
   class TimePrinter implements ActionListener
   {
      public TimePrinter() {
      }
      public void actionPerformed(ActionEvent event)
      {
         Date now = new Date();
         System.out.println("At the tone, the time is " + now);
//         print();
         if (beep) {
            Toolkit.getDefaultToolkit().beep();
//            setBeep(false);
         }
      }
      public void print_inner() {
         System.out.println("inner");
      }
   }
}

局部内部类

局部类不能用publicprivate访问修饰符进行声明。它的作用域被限定在声明这个局部类的块中。

局部类只能访问的局部变量需要是不可变的。需要更改计数时,可以定义一个数组,对数组值进行更新。

局部类并不是直接调用方法传递的参数,而是利用自身的构造器对传入的参数进行备份内部类的方法调用的实际上是自己的属性而不是外部方法传递进来的参数

为什么要将局部内部类访问的局部变量设置为final

简单理解: 拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用 final 来让该引用不可改变。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
public class LocalInnerClassTest
{
   public static void main(String[] args)
   {
      TalkingClock clock = new TalkingClock();
      clock.start(1000, true);
      // keep program running until user selects "Ok"
      JOptionPane.showMessageDialog(null, "Quit program?");
      System.exit(0);
   }
}
class TalkingClock
{
   public void start(int interval,final boolean beep)
   {
      int[] arr = new int[1];
      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();
            arr[0]++;
            System.out.println(arr[0]);
         }
      }
      ActionListener listener = new TimePrinter();
      Timer t = new Timer(interval, listener);
      t.start();
   }
}

匿名内部类

  1. 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
  2. 匿名内部类中是不能定义构造方法的。
  3. 匿名内部类中不能存在任何的静态成员变量和静态方法。
  4. 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
  5. 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
public class AnonymousInnerClassTest
{
   public static void main(String[] args)
   {
      TalkingClock clock = new TalkingClock();
      clock.start(1000, true);
      // keep program running until user selects "Ok"
      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();
//            }
//         };
      // 使用lambda表达式
      ActionListener listener = 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();
   }
}

由于匿名内部类没有构造方法,所以只能通过构造代码块来进行构造

语法形式:

new 实现接口()
{
    //匿名内部类类体部分
}
new 父类构造器(实参列表)
{
  //匿名内部类类体部分
}

abstract class Person {
    public abstract void eat();
}
interface Player {
    void play();
}
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            @Override
            public void eat() {
                System.out.println("eating");
            }
        };
        p.eat();
        Player player = new Player() {
            @Override
            public void play() {
                System.out.println("playing");
            }
        };
        player.play();
    }
}

静态内部类

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

只能在内部类中定义静态类。静态内部类的对象除了没有对生成它的外部类对象的引用特权外,与其他所有内部类完全一样。

静态类只能引用外部类的static成员变量或方法

只有静态内部类可以定义static成员变量或方法,普通的内部类不行!

创建一般内部类和静态内部类的区别:

//假设类A有静态内部类B和非静态内部类C,创建B和C的区别为:
A a=new A();
//创建B
A.B b=new A.B();
//创建C
A.C c=a.new C();

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());
        // 调用静态内部类的静态变量和静态方法
        ArrayAlg.Pair.print();
        System.out.println(ArrayAlg.Pair.NUMBER);
    }
}
class ArrayAlg
{
    private static final boolean flag = false;
    public static void outerClassMethod(){
        System.out.println("inner method");
    }
    public static class Pair
    {
        private double first;
        private double second;
        public static final Integer NUMBER = 20;
        public Pair(double f, double s)
        {
            first = f;
            second = s;
        }
        public double getFirst()
        {
            return first;
        }
        public double getSecond()
        {
            return second;
        }
        // 静态内部类中可以定义静态方法
        public static void print() {
            // 可以调用外部类的静态方法(变量)
            System.out.println("flag: " + flag);
            outerClassMethod();
            System.out.println("static method");
        }
    }
    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);
    }
}
相关文章
|
1月前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。
|
1月前
|
算法 Java
12 Java常用类(一)(内部类+object类+包装类)
12 Java常用类(一)(内部类+object类+包装类)
28 5
|
2月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
31 6
|
1月前
|
Java
【Java】内部类、枚举、泛型
【Java】内部类、枚举、泛型
|
3月前
|
Java
一篇文章讲明白Java中内部类详解—匿名内部类
一篇文章讲明白Java中内部类详解—匿名内部类
42 2
|
3月前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
3月前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
22 2
|
4月前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
34 1
|
3月前
|
Java
Java内部类相关内容总结和解读
Java内部类相关内容总结和解读
25 0
|
3月前
|
存储 Java
Java 五种内部类演示及底层原理详解
Java 五种内部类演示及底层原理详解
24 0