Java学习笔记09

Java学习——Java面向对象03(面向对象高级 上)


一、继承

(1). 继承

先举例:

//最基本的Person类
public class Person {
	public String name;
	public int age;
	
	//构造方法
	public Person() {
	}
	
	//属性的获得与赋值方法
	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 void show() {
		System.out.println("这是个人,姓名:" + name + ",年龄为:" + age);
	}

}

其次我们要定义一个学生类,学生满足Person类的属性及方法,所有可以使用继承方法:

//从Person类继承而来的Student类
public class Student extends Person{
	private String school;
	
	public Student(){
		super();
	}

	public String getSchool() {
		return school;
	}

	public void setSchool(String school) {
		this.school = school;
	}

//父类方法重写
    @Overridde
	public void show() {
		System.out.println("这是个学生,姓名:" + name + ",年龄为:" + age + ", 学校为:" + school);
	}
}

用一个Test类测试上面的情况:

//Test类
public class Test{
	public static void main(String[] args) {
		Student s = new Student();
		s.setName("张三");
		s.setAge(20);
		s.setSchool("小小小学");
		s.show();
	}
}

运行结果:
在这里插入图片描述
分析:
我们使用的Student类 继承了 Person类,从而得以使用Person类里的属性及方法。在使用子类构建的对象时,会先加载父类。

继承:
Student类继承了Person类中的所有成员变量和方法,从上述代码可以见继承使用的关键字是 extends,extends后面的Person是父类
如果在类的声明中没有使用extends关键字指明其父类,则默认父类为Object类。
所以说java.lang包中的Object类是 Java的根类,所有Java类包括数组都直接或间接继承了Object类,在Object类中定义了一些有关面向对象机制的基本方法,如equals()、toString()等方法。
例如我们定义一个类:

 public class Person{ }

其实它被使用时,是这样的:

 public class Person extends Object{ }

两者是一样的,不过是默认没有显示后面的继承。

子类继承父类是有访问权限限制的,限制来自权限修饰符:
在这里插入图片描述

也就是说当我们将Person类的属性,比如 name 或 age 前面的修饰符从public改为private时,子类Student便不能使用了。

(2). 调用父类的构造方法

构造方法是加载类时,自动调用的。
当子类实例化时,不仅需要初始化子类成员变量, 也需要初始化父类成员变量,初始化父类成员变量需要调用父类构造方法,子类使用 super 关键字调用父类构造方法。
例如,我么将上面的Person类中的构造方法,构建一个多参构造方法:

//Person类
//构造方法
public Person(String name,int age) {
	System.out.println("Person类被创建!");
	this.name = name;
	this.age = age;
}

在Student类中构建多参构造方法:

//Student类
	public Student(String name,int age,String school){
		super(name,age);		
		System.out.println("Student类被创建!");
		this.school = school;
	}

运行结果:

在这里插入图片描述
有两个注意点:
输出按照顺序的不同类被创建的语句,可以看到,在使用子类对象构造方法时,先创建Student的父类。
我们若是在子类Student中的构造方法中将调用父类Person的构造方法 Super() 方法向下挪的时候发现报错。

结果:super调用父类构造方法必须位于子类构造方法的第一行,并且调用this不能和super()同时调用,不合乎逻辑
在这里插入图片描述

(3). 方法的重写

如果子类方法完全与父类方法相同,即:相同的方法名、相同的参数列表和相同的返回值,只是方法体不同,这称为子类覆盖或重写(Override)父类方法。
我们在子类Student中,以注解@Override开头,重写了父类Person的show() 方法。在声明方法时添加@Override注解,@Override注解不是方法覆盖必须的,它只是锦上添花,但添加@Override注解有两个好处:

  1. 提高程序的可读性。
  2. 编译器检查@Override注解的方法在父类中是否 存在,如果不存在则报错。

注意方法重写时应遵循的规则:

  1. 参数列表必须完全与父类被重写的方法相同。
  2. 返回类型必须完全和被重写的方法的返回类型相同
  3. 重写后的方法不能比原方法有更严格的访问控制(可以相同)。例如将子类重写的方法show() 代码访问控制public修改private,那么会发生编译错误,但是可以声明
  4. 覆盖后的方法不能比原方法产生更多的异常。
  5. 父类的成员方法只能被它的子类重写
方法重写(Override)与方法重载(Overload)的区别:
  1. 发生的位置:
    重载:一个类中
    重写:子父类中
  2. 参数列表限制:
    重载:必须不同
    重写:必须相同
  3. 返回值类型:
    重载:与返回类型无关
    重写:返回类型必须一致
  4. 访问权限:
    重载:与访问权限无关
    重写:子类的方法访问权限必须不能小于父类的方法访问权限
  5. 异常处理:
    重载:与异常无关
    重写:异常范围可以更小,但是不能抛出新的异常

二、多态

多态概念: 就是对象的多种表现形式,(多种体现形态)。
发生多态要有三个前提条件:

  1. 继承。多态发生一定要子类和父类之间。
  2. 覆盖。子类覆盖了父类的方法。
  3. 声明的变量类型是父类类型,但实例则指向子 类实例。

方法的 重载 和 重写 也是多态的一种,不过是方法的多态(相同方法名的多种形态)。
重载: 一个类中方法的多态性体现
重写: 子父类中方法的多态性体现

(1). 多态的使用

类似于基本数据类型的转换:
· 向上转型:将子类实例变为父类实例

格式:父类 父类对象 = 子类实例 ; 

· 向下转型:将父类实例变为子类实例

格式:子类 子类对象 = (子类)父类实例 ;

其中类型转换可以用关键字 instanceof ,判断某个对象是否是指定类的实例。

格式:实例化对象 instanceof 类 //此操作返回boolean类型的数据

例:将 一、继承 中其余代码不变,Test.java代码调整为:

//Test.java
public class Test {

	public static void main(String[] args) {
		Student s = new Student("张三",20,"小小小学");
		Person p = new Person();
		say(p);
		say(s);
	}
	
	public static void say(Person p) {
		if(p instanceof Student) {
			Student s = (Student)p;
			s.show();
		}else System.out.println("需要传入Student类型!!");
	}
}

运行结果:
在这里插入图片描述
用以验证 关键字 instanceof 功能。



三、再谈 final 关键字

为了声明常量使用过final关 键字,在Java中final关键字的作用还有很多,final 关键字能修饰变量、方法和类。

(1). final修饰变量

final修饰的变量即成为常量,只能赋值一次,但是 final所修饰局部变量和成员变量有所不同。

  1. final修饰的局部变量必须使用之前被赋值一次才能使用。
  2. final修饰的成员变量在声明时没有赋值的叫“空白final变量”。空白final变量必须在构造方法或静态代码块中初始化

例如:

class FinalDemo { 
void doSomething() { 
// 没有在声明的同时赋值
final int e; 
// 只能赋值一次 
e = 100; 
System.out.print(e); 
// 声明的同时赋值 
final int f = 200; 
}
//实例常量 
final int a = 5; 	// 直接赋值 
final int b; 	// 空白final变量 

//静态常量 
final static int c = 12;	// 直接赋值 
final static int d; 	// 空白final变量 

// 静态代码块 
static { 
// 初始化静态变量 
d = 32; 
}
// 构造方法 
FinalDemo() {
// 初始化实例变量 
b = 3; 
// 第二次赋值,会发生编译错误 
// b = 4; 
} 
}

(2). final修饰类

final修饰的类不能被继承。有时出于设计安全的目的,不想让自己编写的类被别人继承,这时可以使 用final关键字修饰父类。

(3). final修饰方法

final修饰的方法不能被子类覆盖。有时也是出于设计安全的目的,父类中的方法不想被别人覆盖,这时可以使用final关键字修饰父类中方法。

总结

接触高级面向对象方法(上),( ̄︶ ̄)↗ !!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值