Java核心技术(五):接口与内部类

一、接口

  • 接口中只能有:常量域、未实现的方法。不能包括实例域、静态方法、方法实现,提供实例域和方法实现的任务应该由实现接口的那个类来完成。
  • 有些接口只定义了常量,而没有定义方法。但最好不要这样使用接口。
  • 接口中的所有方法自动地属于public,接口中的域将被自动设为 public static final。
  • 可以将接口看成是没有实例域的抽象类,但是这两个概念还是有一定区别的。
  • 接口与抽象类的最大区别是:接口可以多继承,而所有类包括抽象类只能单继承。

1.实现接口的步骤

  为了让类实现一个接口,通常需要下面两个步骤∶

  • 将类声明为实现给定的接口。
  • 对接口中的所有方法进行实现。
	class Employee implements Comparable{
    
    //将类声明为实现给定的接口
	
		public int compareTo(Object otherObject){
    
    //实现接口中的方法
			…………
		}
	}

  需要注意的是,接口中方法没用关键字修饰,但默认是public;实现类中,方法一定要用public修饰,因为如果不用任何关键字修饰则默认是包可见。总之,实现类的可见性不能比抽象类的低,子类的可见性不能比父类的低。

  有必要考虑泛型:

	class Employee implements Comparable<Employee>{
    
    //将类声明为实现给定的接口
	
		public int compareTo(Employee otherObject){
    
    //实现接口中的方法
			…………
		}
	}

2.接口的特性

  • 接口不是类,尤其不能使用 new 运算符实例化一个接口∶
	x = new Comparable(..); // ERROR
  • 然而,尽管不能构造接口的对象,却能声明接口的变量∶
	Comparable x; // 0K
  • 接口变量必须引用实现了接口的类对象。
  • 接下来,如同使用 instanceof检查一个对象是否属于某个特定类一样,也可以使用 instance 检查一个对象是否实现了某个特定的接口∶
	if (an0bject instanceof Comparable){
    
     ...}
  • 接口之间可以继承,并且一个接口可以继承多个接口。

二、对象克隆

  由于对象的复制只能拷贝引用,所以我们用clone()方法来拷贝对象指向的值。

  但是,默认的克隆操作是浅拷贝,它并没有克隆包含在对象中的内部对象。也就是说,如果对象的指向仍是引用对象,拷贝的是它的引用。

在这里插入图片描述

  如果进行浅拷贝会发生什么呢?这要根据具体情况而定。如果原始对象与浅克隆对象共享的子对象是不可变的,将不会产生任何问题。但更常见的情况是子对象可变,因此必须重新定义 clone 方法,以便实现克隆子对象的深拷贝。

  即使clone 的默认实现(浅拷贝)能够满足需求,也应该实现 Cloneable接口,将clone重定义为 public,并调用 super.clone( )。下面是一个示例∶

	class Employee inplements Cloneable
	{
    
    
		……
		public Employee clone() throws CloneNotSupportedException //如果在方法中没有实现clone方法,就会抛出异常
		{
    
    
			Employee cloned = (Employee)super.clone();
			cloned.hireDay=(Date)hireDay.clone();
			return cloned;
		}
	}	

  clone方法多少有些笨重,我们应该避免使用它。

三、内部类

  内部类是定义在另一个类中的类。

1.常规内部类

  • 内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。
  • 内部类声明为私有的,使得只有其外部类能访问它。只有内部类可以是私有类,而常规类只可以具有包可见性,或公有可见性。
  • 在类中如何使用外部类引用:外部类名.this
  • 外部类、内部类的引用:
	OuterClass o1=new OuterClass();
	OuterClass.InnerClass o2= o1.new InnerClass();

2.局部内部类

  • 可以在一个类的方法中定义局部内部类。
  • 局部内部类可以访问方法的参数,但该参数必须被声明为final。
	class Outer
	{
    
    
		public void start(int i,final int j)//内部类能访问j,但无论如何j是不可以修改的
		{
    
    
			class Inner
			{
    
    
				public int getJ()
				{
    
    
					return j;
				}
			}
		}
	}

3.匿名内部类

  将局部内部类的使用再深入一步,假如只创建这个类的一个对象,就不必命名了,这种类被称为匿名内部类。

	public void start(int interval,final boolean beep)
	{
    
    
		//匿名内部类的实现,不一定是要实现一个接口,也可以是一个类,在花括号中需要对该类进行扩展
		ActionListener listener = new ActionListener()
		{
    
    
			public void ationPerformed(ActionEvent event){
    
    //由于ActionListener是一个接口,需要实现接口的方法
				……
			}
		}
	}

4.静态内部类

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

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

  若一个类对象是在静态方法中构造的,则对应的该类只能是静态内部类。只有内部类可以声明为 static。

猜你喜欢

转载自blog.csdn.net/Tracycoder/article/details/112341566