Java教程

Java基础(8)

本文主要是介绍Java基础(8),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

抽象类

面向对象编程的核心就是面向抽象编程,一般在开发过程中依赖抽象,不依赖具体

public class A{
	public void pp(Pig pig){}//如果使用具体类,则不具备灵活性。如果需要使用Cat,则只能修改源代码
}

public class B{
	public void pp(Animal obj){}//调用方法时实际上可以传入任何Animal的子类,例如Pig或者Cat
}

class Animal{}
class Pig extends Anima1{}
class Cat extends Animal{}

简介抽象类

包含抽象方法的类叫做抽象类。抽象类不允许直接创建实例,只能由子类提供方法实现后才能通过子类创建对象

抽象方法就是指没有方法体的方法,方法只做声明,没有具体的实现。抽象方法必须在子类中提供具体实现

  • 抽象类中可以包含抽象方法,不是必须包含抽象方法

语法

public abstract class Animal{}

public class Dog extends Animal{}

Animal an=new Dog();//如果直接new Animal则语法报错

特点

  • 包含抽象方法的类就是抽象类,但是抽象类可以没有抽象方法
public abstract class Animal {
	//方法时有具体实现的,不过是空实现,不是没有方法体
	public void pp(){}
	public abstract void cc();//抽象方法,注意抽象方法不能包含方法体{}
}
  • 抽象类不能直接进行new操作,只能定义具体实现的子类后进行new操作

    • 抽象类中可以定义构造器,也可以不定义构造器,由系统自动提供无参构造器

    • 抽象类不允许new操作,和有没有构造器无关

public abstract class Animal{}//abstract class用于声明抽象类

public class Pig extends Animal{}//具体类必须实现了抽象类中所有抽象方法,否则这个类还是抽象类

Animal an=new Pig();
  • 抽象类和普通类一样可以定义成员方法和成员属性,以及构造器和析构器。只是抽象类允许包含抽象方法
  • 普通类继承抽象类,则必须针对抽象类中的所有抽象方法提供具体实现
public abstract class 动物{
	private String name;
	protected int age;
	//构造器
	public 动物(){}
	public 动物(int age){}
	//普通成员方法
	public void 碎觉(){
	System.out.println("闭着眼睛...");
	public abstract void 行走();//抽象方法
}

public abstract class 哺乳动物 extends 动物{
//没有针对行走这个方法提供实现,则当前子类只能是抽象类
}

public class 人类 extends 哺乳动物{
	public void 行走(){}//允许空实现,但是不能没有实现
}
  • 在具体应用中一般抽象类用于定义规范或者通用的方法

    • 通用方法是为了共享,避免子类重复定义
    • 规范是为严格要求子类必须提供实现
  • 方法只有声明而没有具体的实现,则方法就是抽象方法

    • 不是空实现方法体,是没有方法体
    • 需要使用abstract修改,否则语法报错
    • 抽象方法必须定义在抽象类中,该类也必须使用abstract修饰
  • 抽象方法只能使用范围限定词中的public/protected/package默认,不能使用private

    • public void pp(){}这是一个包含空实现的方法,不是抽象方法
    • public void pp();这是一个没有方法实现的方法。在抽象类中要求必须使用abstract修饰
public abstract void pp();
  • 不允许定义抽象构造器public abstract Animaml();语法报错

    • 抽象类中可以定义构造器,也可以不定义构造器,由系统自动提供默认的无参构造器。但是如果自定义构造器,不允许构造器private
abstract class Animal{
	private Animal(){}
}

class Dog extends Animal{
//因为Anima1中只有一个private构造器,所以Dog构造对象时,不能调用到父类构造器所以报错
}
    
  • 如果需要定义私有构造器,则必须提供带参的非私有的构造器
abstract class Parent2 {
	private Parent2(){}
	public Parent2 (int age) {
	 //this();
	}
}
class Son2 extends Parent2 {
	public Son2() {
		super(10);
	}
}
  • 抽象类或者抽象方法不允许为final

    • final类不允许继承,则不能定义子类
    • final方法不允许子类中覆盖定义,所以不能定义final抽象方法
  • 抽象类中可以定义静态方法

public class Test1 {
	public static void main(String[] args) {
		Parent3.pp();//没有办法直接使用Parent3对象调用
		
		Parent3 p3=new Son3(;
		p3.pp();
	}
}

abstract class Parent3 {
	public static void pp() {
		System.out.println( "Parent. ..pp");
	}
}

class Son3 extends Parent3 {}

  • 抽象类不允许定义抽象静态方法
abstract class Parent3 {
//The abstract method dd in type Parent3 can only set avisibility modifier,one of public or protected
public static abstract void dd();//不允许使用abstract
}

  • 可以使用抽象类直接调用静态方法

  • 抽象类不能直接创建对象,只能通过继承的方式定义子类,然后创建子类对象。子类对象可以赋值给抽象类声明的变量Animal a=new Dog();

  • 抽象类中除了可以抽象方法,也可以有非抽象方法

问题

问:抽象类不能实例化,是否是因为抽象类中没有定义构造器所导致?

答:1、抽象类不能实例化是语法规则,和有没有构造器没有关系;
2、抽象类中可以定义构造器,也可以不定义构造器。如果不定义构造器则系统自动提供无参构造器;
​ 3、创建子类对象时,抽象父类的构造器也会自动被调用执行。

问:抽象类不能实例化,是否因为调用抽象方法没有意义?

答:抽象类可以包含抽象方法,也可以没有抽象方法。没有抽象方法时,抽象类也不能实例化。抽象类必须由子类覆盖定义了父类的所有抽象方法后,子类才可以实例化,否则这个子类还是抽象类。

问:抽象类种有构造器?

答:有,用于给子类对象进行初始化
;new子类时抽象父类的构造器一定会被执行

问:抽象类可以不定义抽象方法?

答:可以的,但是一般较少出现;目的就是不允许构建该类对象,只能被子类继承;通过子类才能构建抽象父类的对象

问:抽象类—定是父类?
答:是的。因为需要子类提供父类抽象方法的实现,才可以进行实例化创建对象时,加载的顺序:

  • 先加载父类

    • 处理父类的静态属性和静态初始化块,两者地位相等,执行顺序取决于定义顺序
    • 静态代码块和静态方法一致,要求只能直接访问静态成员
    • 如果需要在静态代码块和静态方法中访问非静态成员则必须构建对象
  • 加载子类

    • 处理子类的静态属性和静态初始化块,两者地位相等,执行顺序取决于定义顺序。

    • 静态代码块和静态方法一致,要求只能直接访问静态成员

    • 如果需要在静态代码块和静态方法中访问非静态成员则必须构建对象

  • 先加载父类

    • 成员属性和初始化块,两者地位相等,执行顺序取决于定义顺序。
    • 父类构造器
  • 加载子类

    • 成员属性和初始化块,两者地位相等,执行顺序取决于定义顺序

    • 子类构造器

使用场景

  • 当一个类中的一个或者多个方法是抽象方法时
  • 当一个类为抽象类的子类时,并没有为所有的抽象方法提供实现或者提供方法主体时
  • 当一个类实现一个接口时,并没有为接口中的所有方法提供实现细节或者提供方法体时

抽象类的作用

主要用途时进行类型的隐藏。构造出一个固定的一组行为的抽象描述,但是这组行为能够有任意个可能的具体实现方式。

public void pp(动物obj){
obj.work();
obj.公共方法();
public abstract class 动物{
public void 公共方法(){
具体实现;
}
public abstract void work();
class 狗 extends 动物{
public void work(){
System.out.println("看大门!");
}
}

抽象类一般用来表征问题域的分析,设计种经常会先获取抽象类,然后再定义确定的具体类OOP的核心就是面向抽象编程
在父类种固化算法骨架,在子类种实现特殊的方法

抽象类vs普通类

  • 抽象类不能直接实例化,只能通过子类进行实例化;普通类可以直接实例化

  • 抽象类允许包含抽象成员方法;普通类中不允许包含抽象方法

  • 抽象类不允许被密封。final密封类不能被继承,防止恶意的派生

模板模式

属于行为型设计模式

具体编程实现

首先定义一个抽象类公开定义总体的算法(算法骨架),但是有些总体算法中需要使用的方法没有办法实现,所以可以延迟到子类中提供

抽象父类:提供算法骨架,并定义抽象方法

public abstract class Bubb1esorter{
	//在父类中定义算法实现,没有办法定义的比较方法延迟到子类中提供
	public final void sort(object[] arr){
		for(int i=1;i<arr.length;i++){
			for(int k=0 ; k<arr.length-i ; k++){
			//如何实现两个对象的比较
			if(bigger(arr[k],arr[k+1])){
					object tmp=arr[k];
					arr[k]=arr[k+1];
			    	arr[k+1]=tmp;
				}
			}
		}
	}
//由于在父类中没有办法确定如何比较,所以定义抽象方法,要求子类必须提供实现
	protected abstract boolean bigger(object obj1,object obj2);
}

具体的子类中提供具体的比较方法

public class Pig{//比较并排序的对象
	private double weight;
}

针对Pig定义对应的排序器

public class Pigsorter extends Bubblesorter{
	protected boo1ean bigger(object obj1,object obj2){
		if(obj1!=null && obj1 instanceof Pig){
		Pig p1=(Pig)obj1;
		if(obj2 !=null && obj2 instanceof Pig){
			Pig p2=(Pig)obj2;
			return p1.getWeight()>p2.getWeight();
			}
		}
		return false;
	}
}

应用场景

何时使用:有一些通用的方法
如何解决:将这些通用算法抽象出来。

  • 有多个子类共有的方法,且逻辑相同。
  • 重要的、复杂的方法,可以考虑作为模板方法。

优点

  • 封装不变部分,扩展可变部分。

  • 提取公共代码,便于维护。

  • 行为由父类控制,子类实现。

缺点

每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

耦合问题

OOP要求类内高内聚,类间弱耦合—客户需求变动

public class 农场{
	private 冒泡排序器 sorter;
	//农场类和抽象类耦合的,但是不耦合具体的实现类,所以可以在多个实现类之间进行切换
}
这篇关于Java基础(8)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!