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);
    }
}
相关文章
|
2月前
|
Java
java中,剩下的这两个内部类不太好理解!
java中,剩下的这两个内部类不太好理解!
14 0
|
2月前
|
Java 编译器
java中常见的几种内部类,你会几个?(未完)
java中常见的几种内部类,你会几个?(未完)
15 1
|
5月前
|
Java 数据安全/隐私保护
【零基础学Java】—内部类的概念与分类(三十)
【零基础学Java】—内部类的概念与分类(三十)
|
1天前
|
Java
Java一分钟之-Java内部类与匿名类
【5月更文挑战第12天】本文介绍了Java的内部类和匿名类,包括成员内部类和局部内部类,以及匿名类的一次性子类实现。通过代码示例展示了它们的使用方法,同时提到了常见问题和易错点,如混淆内部类与嵌套类、匿名类的生命周期管理及内部类的访问权限,并给出了相应的避免策略。理解这些概念有助于提升代码质量。
17 3
|
3天前
|
Java
Java内部类
Java内部类
8 2
|
24天前
|
Java
什么是Java内部类,为什么使用它?
【4月更文挑战第13天】
18 1
|
1月前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
38 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
1月前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
13 0
|
1月前
|
存储 Java
java接口和内部类
java接口和内部类
|
2月前
|
Java 编译器
详解java各种内部类
详解java各种内部类