Java基础10(this super关键字 重写 final关键字 多态 抽象类)

目录

一. this和super关键字

1. this关键字

2. super关键字

二. 重写

三. final关键字

四. 多态

五. 抽象类

1. 抽象方法

2. 抽象类 

3. 面向抽象设计


一. this和super关键字

1. this关键字

this   当前对象的引用

this.属性
this.方法名()
this()  -- 调用构造函数 放在代码第一行

细节:

●可以用this来区分属性和局部变量。

●在类的方法中,我们可以使用this.属性或this.方法的方式,调用当前对象属性或方法。但是,通常情况下,我们都选择省略this.。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用this.变量的方式,表明此变量是属性,而非形参。
●使用this访问属性和方法时,如果在本类中未找到,会从父类中查找。

调用属性和方法:

class Person{ // 定义Person类
    private String name ;
    private int age ;
    public Person(String name,int age){
      this.name = name ; 
      this.age = age ; }
    public void getInfo(){
      System.out.println("姓名:" + name) ;
      this.speak();
    }
    public void speak(){
      System.out.println(“年龄:” + this.age);
    } 
}

调用构造方法:

●this(形参列表)必须声明在当前构造器的首行

class Person{ // 定义Person类
   private String name ;
   private int age ;
   public Person(){ // 无参构造器
     System.out.println("新对象实例化") ;
   }
   public Person(String name){
     this(); // 调用本类中的无参构造器
     this.name = name ;
   }
   public Person(String name,int age){
     this(name) ; // 调用有一个参数的构造器
     this.age = age;
   }
   public String getInfo(){
     return "姓名:" + name + ",年龄:" + age ;
   } 
}

2. super关键字

super   子类调用父类的内容

super   表示的是超类或者父类的意思

super.属性  调用父类的成员变量
super.方法名() 调用父类的成员方法
super()    调用父类的构造方法

使用:

可以在子类中显示地调用父类的结构。

构造方法里面:
●子类默认调用父类无参构造方法super()

●如果父类没有无参构造,则需要手动使用super(参数)来调用父类的有参构造
●如果显示的写了super(参数),默认的则不赠送
●super()一定是在第一行
●this()必须写在第一行,所以super()和this()不能同时出现

父类:

public class Person {
	protected String name;
	protected int age;
 
	public String getName() {
		return name;
	}
 
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public int getAge() {
		return age;
	}
 
	public void setAge(int age) {
		this.age = age;
	}
 
}

子类:

public class Student extends Person {
	private int score;
 
	public Student() {
		//默认调用父类无参构造方法
		// super();
		//调用父类的有参构造方法
		super("zkt",18);
	}
 
}

3. this和super的区别

关键字访问成员变量访问成员方法访问构造方法
thisthis.本类成员变量;this.本类成员方法();this();this(...);本类构造方法
supersuper.父类成员变量;super.本类成员方法();super();super(...);本类构造方法
●this()和super()都在争夺构造方法第一行的位置,所以二者不能共存

二. 重写

在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为重写(Override)

语法规则:

在子类和父类中有方法名完全一致,返回值类型相同的方法

发生在子类和父类中,如果父类所提供的方法不能满足子类的需求,则子类可以重写
方法名相同,参数项相同,返回值也相同,子类的修饰符>=父类的修饰符,方法体不同

   返回值:子类重写的方法的返回值范围可以小于父类的方法的返回值范围

父类:

class Person {
    public void run() {
        System.out.println("Person.run");
    }
}

子类: 在子类Student中,重写这个run()方法

class Student extends Person {
    @Override
    public void run() {
        System.out.println("Student.run");
    }
}


手动重写Object类的方法:

在Java中,所有的class类最终都继承自Object,而Object定义了几个重要的方法

@Override
	public String toString() {
		return "姓名" + name + "身份证号:" + cardId;
	}

	// equals 只能用在引用数据类型上
	// object中的equals方法比较的是两个对象的地址是否相同,String类比较的是内容是否相同(因为其重写了equals方法)
	// 如果自己想要看内容是否相同 重写equals方法
	@Override
	public boolean equals(Object obj) {
		// 1.先比较地址是否相同
		if (this == obj) {
			return true;
		}
		// 2.先判断是否是Person类型
		if (obj instanceof Person) {
			// 向下转型
			Person p1 = (Person) obj;
			return this.name.equals(p1.name) && this.cardId.equals(p1.cardId);
		}
		return false;
	}

	// 地址改成了属性的地址和
	// 如果两个对象的属性完全相同 则hashCode值也完全相同
	@Override
	public int hashCode() {
		return name.hashCode()+cardId.hashCode();
	}

重载:

●方法的重载:在同一个类中,方法名相同,参数项不同(类型,个数,顺序)

●和返回值无关,发生在编译期

重载重写的区别:

N区别重载重写
1概念方法名称相同,参数的类型及个数不同方法名称、返回值类型、参数的类型及个数完全相同
2范围一个类继承关系
3限制没有权限要求被重写的方法不能拥有比父类更严格的访问控制权限

三. final关键字

继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。

父类:

public class Fu {
	public final int AGE = 18;
	public final int[] AAA = { 12, 2, 23, 45 };

	public final void eat() {
		System.out.println("这个是父类的eat方法");
	}
}

1.1:final用来修饰字段基本数据类型,常量-值不可变

	//1.1:final用来修饰字段基本数据类型,常量-值不可变
		Fu fu1 =new Fu();
//		fu1.AGE=10;
		System.out.println(fu1.AGE);//18

1.2:final用来修饰字段(引用数据类型)地址不可发生变化,值可以变

fu1.AAA[0]=1000;
		System.out.println(Arrays.toString(fu1.AAA));//[1000, 2, 23, 45]

2.final用来修饰方法,此方法不能重写,此方法可以被子类调用

//2.final用来修饰方法,此方法不能重写,此方法可以被子类调用
		Zi zi  = new Zi();
		zi.eat();//这个是父类的eat方法
class Zi extends Fu{
	// compile error: 不允许覆写
	@Override
	public void eat() {
		System.out.println("这个是子类的eat方法");
	}
}

3.fianl用来修饰类,父类不能被继承,太监类

四. 多态

多态指的是同一对象,在不同时刻表现出来的多种形态

多态实现的三要素:

●有继承关系/实现关系
●有方法的重写
●有父类的引用指向子类,向上转型

示例:

Shape类:

public class Shape {
	public void draw() {
	}
}

子类:

class Circle extends Shape {
	@Override
	public void draw() {
		System.out.println("⭕");
	}
}
class Flower extends Shape {
	@Override
	public void draw() {
		System.out.println("❀");
	}
}
class Star extends Shape {
	@Override
	public void draw() {
		System.out.println("⭐");
	}
}
class Triangle extends Shape {
	@Override
	public void draw() {
		System.out.println("▲");
	}
}
class Square extends Shape {
	@Override
	public void draw() {
		System.out.println("■");
	}
}

不使用多态写法:

public static void main(String[] args) {
		Flower flower = new Flower();
		Star star = new Star();
		Circle circle = new Circle();
		Triangle triangle = new Triangle();
		Square square = new Square();
		String[] shapeStrings = { "flower", "star", "circle", "triangle", "square" };
		// 不使用多态绘制图形
		for (int i = 0; i < shapeStrings.length; i++) {
			if ("flower".equals(shapeStrings[i])) {
				flower.draw();
			} else if ("star".equals(shapeStrings[i])) {
				star.draw();
			} else if ("circle".equals(shapeStrings[i])) {
				circle.draw();
			} else if ("triangle".equals(shapeStrings[i])) {
				triangle.draw();
			} else if ("square".equals(shapeStrings[i])) {
				square.draw();
			}
		}
	}

多态写法:

public static void main(String[] args) {
		Shape[] shapes = {new Flower(),new Star(),new Triangle(),new Square()};
		for (Shape shape : shapes) {
			shape.draw();
		}
	}


多态的写法优点:

●类的调用者对类的使用成本进一步降低,多态是让类的调用者不用知道类的具体类型.
●可以降低圆圈复杂度
●可拓展性增强

多态的写法:

父类 对象名= new 子类() #父类类型指向子类对象   eg: Fu  fu = new Zi()
接口 对象名= new 实现类() #接口类型指向实现类对象

多态中的成员访问特点:见java基础09

●成员变量的访问特点:看等号左边

●成员方法的访问特点: 编译看左边,运行看右边,如果没有则向上查找。

多态的优缺点:

优点:父类类型/接口类型作为方法的参数/返回值,提高了程序的扩展性

缺点:无法访问子类/实现类中独有的方法。(需要向下转型)

向上下转型:见java基础09

五. 抽象类

在抽象类中,抽象方法本质上是定义行为规范:规定父类中的抽象行为(抽象方法),要求所有子类必须对该抽象方法进行实现。从而,实现对子类行为规范的约束。主要用于实现多态。

●当一个类被abstract修饰这个类就是抽象类

●在Java中,—个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

1. 抽象方法

抽象方法:
●抽象方法没有方法体
●抽象方法使用abstract关键字来修饰,修饰符和返回值中间

修饰符 abstract 返回值类型 方法名();

●抽象方法必须写在抽象类中
●抽象方法的修饰符不能是private

public abstract class Shape {
	// 定义了一个"规范"
		public abstract void draw();
}

2. 抽象类 

抽象类:
●抽象类使用abstract关键字来修饰,放在修饰符和class中间
●子类必须要重写抽象类中的抽象方法,除非子类也是抽象类
●抽象类无法实例化对象
●抽象类中有成员变量,常量,构造方法(存在的意义,初始化成员变量) 抽象方法 --规范

public abstract class Shape {
	public int age;
	public final double PI = 3.14;

	public Shape() {
		this.age = 18;
		System.out.println("这个是父类的无参构造方法");
	}

	// 定义了一个"规范"
	public abstract void draw();

	public void doSth() {
		System.out.println("这个是shape的doSth方法");
	}
}

●子类是抽象类,可以不用实现抽象方法,当然也可以实现抽象方法(如果在此处可以完成)

        

//子类是抽象类,可以不用实现抽象方法,当然也可以实现抽象方法(如果在此处可以完成)
abstract class Circle extends Shape {

}

●子类是普通类,必须要重写父类中的抽象方法

//子类是普通类,必须要重写父类中的抽象方法
class Flower extends Shape {
	public Flower() {
		super();
	}

	@Override
	public void draw() {
		System.out.println("❀");
	}
}

●抽象类不能实例化对象

报错

		Circle c1 =new Circle();//抽象类不能实例化对象
		Shape s1 = new Shape();

子类调用:

Flower f1 = new Flower();
		System.out.println(f1.age);
		f1.doSth();

多态写法:

	Shape s1 = new Flower();//多态写法
		s1.doSth();
		s1.draw();

3. 面向抽象设计

面向抽象设计的本质是:
●上层代码只定义规范(例如:abstract class Person)
●不需要子类就可以实现业务逻辑(正常编译)
●具体的业务逻辑由不同的子类实现,调用者并不关心

public abstract class Person {
	protected String name;

	public Person(String name) {
		super();
		this.name = name;
	}

	// 定义了规范
	public abstract void run();
}
class Student extends Person {

	public Student(String name) {
		super(name);
	}

	@Override
	public void run() {
		System.out.println("学生类"+name+"的run方法");
	}

}
class Teacher extends Person{

	public Teacher(String name) {
		super(name);
	}

	@Override
	public void run() {
		System.out.println("老师类"+name+"的run方法");
	}
	
}

这种引用抽象类的好处在于,我们对其进行方法调用,并不关心Person类型变量的具体子类型:

Person[] persons = { new Student("zkt1"), new Student("zkt2"), new Teacher("zkt3") };
		for (Person person : persons) {
			//在运行的过程中,不必过多关注子类的业务实现,也不必关注子类的具体类型
			person.run();
		}

  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯诺依曼转世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值