版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37726222/article/details/84616370
为什么要使用内部类?
- 内部类可以访问该类定义所在的作用域中的所有的数据,包括私有数据
- 内部类可以对同一个包的其他类隐藏起来
- 当要定义一个回调函数并且不想编写大量代码时,使用匿名内部类比较方便。
使用内部类访问对象的状态
内部类的对象总有一个隐式引用。它指向了创建它的外部类对象。
在一个内部类的对象被创建之时,它所在类的对象的引用被作为参数,传递给这个内部类的隐式构造函数。
内部类的特殊语法规则
- OuterClass.this 引用外部类的对象 eg
Talking.this.beep
ActionListener listenr =this.new TimePrinter();
在这里,最新构造的actionListener对象的外围类的引用被设置为创建内部类对象的方法中的this引用。- 在外围类的作用域之外,
Outerclass.innerclass
可以这样引用内部类 - 内部类中所有的静态域必须是final
内部类是否有用,必要和安全?
与常规类相比,内部类访问外围类私有数据的特性更强大
内部实现?
- 编译器会在外围类中添加
static boolean access$0(TalkingClock)
这样的access$0方法
局部内部类
局部内部类适用于内部类的对象只使用一次的情况。
- 局部类不能用public 或 private修饰。
- 局部类的优势是,只在一个方法内定义,只被一个方法使用。其他类不知道该局部类的存在。
由外部方法访问变量 P252
与内部类相比较,局部类的另一个优点是,可以访问局部变量。
局部类的方法只可以引用定义为final的局部变量。对于counter这种final不方便的情况,可以用长为1的数组来存储。
匿名内部类
匿名内部类的格式?
new SuperType(construction parameters)
{
inner class methods and data;
}
注意匿名类没有类名。故没有构造器。
如果有参数,作用是啥?参数传递给超类的构造器。(上面就是个例子)
但是,对于内部类实现接口的时候:不能有参数!
new InterfaceType()
{
inner class methods and data;
}
下面是用匿名内部类实现语音时钟程序的源代码:
/**
* A clock that prints the time in regular intervals.
*/
class TalkingClock
{
/**
* Starts the clock.
* @param interval the interval between messages (in milliseconds)
* @param beep true if the clock should beep
*/
public void start(int interval, boolean beep)
{
ActionListener listener = new ActionListener()//这是一个接口
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is " + new Date());
if (beep) Toolkit.getDefaultToolkit().beep();
}
};
Timer t = new Timer(interval, listener);
t.start();
}
}
但此处用lambda表达式会更加的简洁。
小注释:匿名数组列表:
invite
(
new ArrayList<String>()
{
{
add("Harry");
add("Tony");
}
}
)
匿名子类在使用equals方法时要特别当心!
getClass()方法在使用时调用的是this.getClass(),但是静态方法没有内部类,这就不行了
怎么办?
new Object(){}.getClass.getEnclosingClass()
这样就得到了包含这个静态方法的类。可以算是匿名子类的一个应用吧。
静态内部类
为什么要静态?
有时候不需要内部类引用外围类的对象,所以声明该内部类为static,取消产生引用。
静态内部类的对象除了没有对生成它的外围类对象的引用特权外,与其他所有内部类完全一样。
与常规内部类不同,静态内部类可以有静态域和方法。
下面是一个静态内部类的例子:
class ArrayAlg
{
/**
* A pair of floating-point numbers
*/
public static class Pair
{
private double first;
private double second;
/**
* Constructs a pair from two floating-point numbers
* @param f the first number
* @param s the second number
*/
public Pair(double f, double s)
{
first = f;
second = s;
}
/**
* Returns the first number of the pair
* @return the first number
*/
public double getFirst()
{
return first;
}
/**
* Returns the second number of the pair
* @return the second number
*/
public double getSecond()
{
return second;
}
}
/**
* Computes both the minimum and the maximum of an array
* @param values an array of floating-point numbers
* @return a pair whose first element is the minimum and whose second element
* is the maximum
*/
public static Pair minmax(double[] values)
{
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
for (double v : values)
{
if (min > v) min = v;
if (max < v) max = v;
}
return new Pair(min, max);
}
}
下面是调用的方法:
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());
}
注意此处,内部类对象在静态方法中构造,所以必须使用静态内部类。