java 基础——面向对象编程之抽象类、密封类、接口

抽象类和抽象方法

 对于一个父类来说,如果其某个方法在父类之中实现出来没有任何意义,必须根据子类情况来进行不同的实现。那么就可以将当前方法声明为抽象方法,包含抽象方法的类  称为抽象类。

下面就是一个抽象类,用abstract 修饰的类就是一个抽象类。

abstract class Animal1{
	abstract public void cry();//抽象方法不做具体实现。
	public void fun1(){//非抽象类
    }
}

关于抽象类要注意的问题:

  • 抽象类不能被实例化成一个对象。
  • 抽象类中可以有抽象方法,也有可以非抽象方法。
  • 类中只要有抽象方法则必须被定义为抽象类。

抽象类和普通类的区别:

  • 抽象类的子类必须实现父类的抽象方法。
  • 抽象类必须设置权限为public 或者 protect , 缺省默认为public,private修饰的类被子类继承,所以不能修饰抽象方法
  • 抽象类不能实例化一个对象。

抽象类的子类必须实现父类的抽象方法。

class Dog1 extends Animal1{
	@Override
	public void cry() {
		System.out.println("wangwang.....");
		
	}
}

如果一个抽象类继承了一个抽象类,那么可以不实现基类的抽象方法。

//如果一个抽象类继承了一个抽象类,那么可以不实现基类的抽象方法。
abstract class Cat1 extends Animal1{
	abstract public void cry();
}
如果一个类再次继承了这个抽象类,必须进行实现抽象方法。
//如果一个类再次继承了这个抽象类,必须进行实现抽象方法。
class LittleCat extends Cat1{
	@Override
	public void cry() {
		System.out.println("littleCat....");
	}
}

密封类和密封方法

类和方法 被final修饰之后,类不能被继承,方法不能被修改。

class Base4{
	//密封方法.表明当前方法不能被再次修改。
	public final void fun1(){
		System.out.println("base.fun1");
	}
	public void fun2(){
		System.out.println("base.fun2");
	}
}
class Derive4 extends Base4{
	/*public void fun1(){
		System.out.println("Derive.fun1");
	}*///报错
	public void fun2(){
		System.out.println("Derive.fun2");
	}
}

密封类的优点:

密封类可以防止有意的派生。

接口

接口主要是对行为进行抽象。

默认数据成员为 public static final。

默认成员方法为 public abstract(成员方法不能有具体的实现)。

interface A{ 
	int age = 10;
	void fun1();
	public static final int age = 10;
	public abstract void fun1();
}
interface B{
	int b = 100;
	void fun2();
}

在上面的方法中对于成员变量写不写 public static final 都一样,它默认就是 public static final。

接口的实现

每个类可以实现多个接口。

接口不可以实现接口。

class C implements A,B{

	@Override
	public void fun1() {
		System.out.println("A.fun1");
	}

	@Override
	public void fun2() {
		System.out.println("B.fun2");
	}
}

接口的继承

接口和接口之间可以继承。

interface A{
	public void fun1();
}
interface B{
	public void fun2();
}
interface C extends A,B{//接口 C 继承接口 A 和 B.
	public void fun3();
}
class X implements C{//类 X 实现接口 C 必须实现接口A、B、C 里面所有的方法。

	@Override
	public void fun1() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fun2() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fun3() {
		// TODO Auto-generated method stub
		
	}
}


接口和抽象类的区别

接口可以被实现多个(解决了 java 的单继承问题),抽象类只能被继承一个。

抽象类可以拥有非抽象方法,而接口内都是抽象方法。

接口的数据成员变量都是public static final

接口是对行为的一种抽象,抽象类本身是对类整体的抽象。

接口的应用

 Cloneable

Cloneable 接口是对对象的克隆,可以通过调用 clone( )方法对对象进行克隆。

class Money implements Cloneable{
	double money = 10.0;
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
class Person implements Cloneable{
	public String name;
	Money m;
	public Person(String name) {
		this.name = name;
		m = new Money();
	}
	//重写 Object 克隆方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		//Person 的重写
		Person p = (Person)super.clone();
		p.m = (Money)this.m.clone();//对当前对象的引用进行克隆
		return p;
	}
}
public static void main(String[] args) throws Exception {
		Person p1 = new Person("caocao");
		Person p2 = (Person)p1.clone();
		System.out.println("p1:"+p1.m.money);
		System.out.println("p2:"+p2.m.money);
		p1.m.money = 1000;
		System.out.println("===========");
		System.out.println("p1:"+p1.m.money);
		System.out.println("p2:"+p2.m.money);
	}

运行结果:

p1:10.0

p2:10.0

===========

p1:1000.0

p2:10.0


注意,在 People clone( )中如果不对当前引用的对象进行克隆,则改变 p1.m.money 的值,p2.m.money 的值也接着改变。

因为此时两个对象指的是同一个 m。入下图所示。



如果对当前 Money 这个对象的引用克隆后,则入下图。


注意 
此接口在使用的时候,clone()方法和 Cloneable 接口必须同时使用,不可单独使用,如果单独使用就会报异常,因为JVM(Java虚拟机)需要一个接口当做标志位,来判别其是否可以被克隆。

Comparable 接口

class Person1 implements Comparable<Person1>{
	private String name;
	private int age;
	private double score;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}
	public Person1(String name,int age,double score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	@Override
	public String toString() {
		return "Person1 [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	//待排序的数据
	public int compareTo(Person1 o) {
		return age - o.age;
	}
}
	public static void main(String[] args) {
		Person1[] array = new Person1[3];
		array[0] = new Person1("caocao",18,29.0);
		array[1] = new Person1("aliubei",19,30.0);
		array[2] = new Person1("erke",21,10.0);
}
运行结果:

[Person1 [name=caocao, age=18, score=29.0], Person1 [name=aliubei, age=19, score=30.0], 

Person1[name=erke, age=21, score=10.0]]


Comparable 接口里面有一个 ComparaTo 方法,必须在子类实现它。


 sort(Object[] a)  这是一个专门为了数组排序的方法。

Comparator 比较器

public static void main(String[] args) {
		Person1[] array = new Person1[3];
		array[0] = new Person1("caocao",18,29.0);
		array[1] = new Person1("aliubei",19,30.0);
		array[2] = new Person1("erke",21,10.0);
		
		//对数组内的数据根据年龄排序
		Arrays.sort(array,new Comparator<Person1>(){
			//传入的时候有由用户自己选择,
			@Override
			public int compare(Person1 p1, Person1 p2) {
				int age1 = p1.getAge();
				int age2 = p2.getAge();
				return age1 > age2 ? age1 : (age1 == age2) ? 0 : -1;
			}
		});
		System.out.println(Arrays.toString(array));
}

运行结果:

    [Person1 [name=caocao, age=18, score=29.0], Person1 [name=aliubei, age=19, score=30.0], 

    Person1[name=erke, age=21, score=10.0]]



Comparator 比较器是一个接口,我们必须重写实现里面的方法,使得它可以按照用户的需求来执行操作,比较灵活。

接口虽然不能创建一个对象,但是可以创建一个匿名内部类。

public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, c);
    }
这个方法是用 Comparator 比较器来对对象排序。

猜你喜欢

转载自blog.csdn.net/alyson_jm/article/details/80445354