final关键字:final是最终的意思,可以修饰类,变量,成员方法
1. final 修饰类, 该类就不能被继承
2. final 修饰方法, 该方法就不能在子类中被覆盖
3. final 修饰变量
a. final修饰局部变量, 该局部变量,只能被赋值一次且仅一次
b final修饰成员变量,我们必须保证,在对象创建完毕之前,我们自己必须给该
成员变量赋值一次,且仅一次
被final修饰的变量,其实就变成了一个自定义常量
a. 因为其值在程序运行期间不能被改变
b. 自定义体现在,常量的名字是我们自定义的
注意事项:
如果我们定义多个构造方法,而且我们是通过构造方法给final修饰的成员变量赋值,
一定要保证,每个构造方法,都要给final修饰的成员变量赋初值
public class Demo1 {
}
final class A {}
// 被final修饰的类,不能被继承
//class B extends A{}
class Father {
public final void method() {
System.out.println("method");
}
}
class TestFinal extends Father {
// @Override
// public void method() {
// System.out.println("method");
// }
final int finalValue1;
final double finalValue2;
// 通过成员变量的初始化语句,在对象创建完毕之前,给final修饰的成员变量赋初值
final boolean finalValue3 = true;
{
// 利用构造代码块,在对象创建完毕之前,给final修饰的成员变量赋初值
finalValue2 = 200;
//finalValue2 = 89;
}
public TestFinal() {
// 利用构造方法,在对象创建完毕之前,final修饰的成员变量赋初值
finalValue1 = 100;
}
public TestFinal(int finalValue1) {
this.finalValue1 = finalValue1;
}
/*
测试被final修饰的局部变量
*/
public void testLocalVariable() {
final int a = 100;
System.out.println();
//a = 900;
// final 修饰的局部变量只能被赋值一次,且仅一次
//a = 10;
// 自定义常量
}
}
二、多态
/*
多态的好处
提高了程序的维护性(由继承保证)
提高了程序的扩展性(由多态保证)
假设,先在有科学家要研究动物的声音
a. 让动物发出叫声
b. 收集动物的叫声
c. 研究收集到的声音
一开始,科学家之研究猫和狗的声音,过了一段时间,科学家想收集新的动物的声音猪的声音
*/
public class Demo2Benefit {
public static void main(String[] args) {
Dog dog = new Dog();
// collectDogSound(dog);
//
Cat cat = new Cat();
// collectCatSound(cat);
collectAllSound(dog);
collectAllSound(cat);
// 收集猪的声音
Pig pig = new Pig();
collectAllSound(pig);
}
// 定义方法研究狗的声音
public static void collectDogSound(Dog dog) {
// 狗发出叫声
dog.shout();
// 收集声音
// 研究声音
}
/*
研究猫的声音
*/
public static void collectCatSound(Cat cat) {
// 猫发出叫声
cat.shout();
// 收集声音
// 研究声音
}
/*
收集并研究猫,狗的声音并研究
*/
public static void collectAllSound(Animal animal) {
// 这里会发生多态
animal.shout();
}
}
class Animal {
public void shout() {
System.out.println("动物的叫声");
}
}
class Dog extends Animal {
public void shout() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal {
public void shout() {
System.out.println("喵喵喵");
}
}
class Pig extends Animal {
public void shout() {
System.out.println("猪叫");
}
}
package com.cskaoyan.polymorphism;
/*
Java语言中的多态指什么呢? “同一个对象”的行为,在不同的时刻或条件下,表现出不同的效果。
发生多态的条件:
a. 继承
b. 方法覆盖
c. 父类引用指向子类对象
多态中的成员访问特征
成员变量
编译看左边,运行看左边
成员方法(多态效果)
编译看左边,运行看右边
解释:
1. 编译看左边: 父类引用指向子类对象,此时编看左边是在说,
通过引用变量可以访问到的成员的范围,是由引用类型来决定的
a. 迄今为止,我们是怎么去访问一个对象?我们都是通过一个中间人即引用变量,间接访问堆上对象
b. 也就是说,只有通过引用变量,我才能访问到堆上的对象
举例:
1). 我们如果把对象,当成我们的一台电视机,对于电视机而言,我们只能使用,遥控器去操作电视机
2). 这也就意味着,遥控器提供了什么样的功能,那我们只能使用,遥控器提供的功能,操作电视机
此时即使电视机提供了很多功能可以使用,但是如果遥控器提供了,极其有限的功能
3). 这意味着,我们可以使用的电视机的功能,被遥控器给限制了
所以,回到java程序,访问对象的时候,引用变量,就是我们用来操作对象的"遥控器",所以引用变量的类型
决定了,可以访问到的成员的范围。
2. 对于成员变量,运行看左边
一个对象 属性(成员变量) 和 行为,一个对象的属性(成员变量表示),表示了一对象的外貌
在多态中,此时对于子类对象而言,把子类对象赋值给父类类型的引用,就相当于给子类对象
披上了一个父类类型马甲, 因此,该子类对象看起来,就是一个父类对象(外貌特征,
表现出的就应该是父类的外貌特征)
3. 对于成员方法的,运行(结果)看 右边(多态)
就是说对于成员方法而言,通过引用变量,实际访问到的行为(方法), 是由引用实际指向的对象来决定的
*/
public class Demo1Basic {
public static void main(String[] args) {
// 测试多态的效果
//testPoly();
// 测试多态成员的访问
//testMemberAccess();
// 父类类型的引用变量
PolyFather polyFather;
// 编译看左边
polyFather = new FirstPolySon();
// 通过父类引用,无法访问到,子类自己定义成员
//polyFather.son();
FirstPolySon first = new FirstPolySon();
// 通过子类应用,才能访问到,子类自己定义的成员
first.son();
// 总结一下,通过引用变量,到底能访问到哪些成员?
// 只和引用变量的类型有关系,而和引用变量所指向的实际类型
}
private static void testMemberAccess() {
// 多态的成员访问特征(成员变量,成员方法)
PolyFather polyFather;
polyFather = new FirstPolySon();
// 通过父类引用访问父类子类定义的同名成员变量值,访问的是父类定义的成员变量值
System.out.println(polyFather.value); // 100
// 多态效果
polyFather.testPolymorphism();
polyFather = new SecondPolySon();
// 通过父类引用访问父类子类定义的同名成员变量值,访问的是父类定义的成员变量值
System.out.println(polyFather.value); // 100
// 多态效果
polyFather.testPolymorphism();
}
private static void testPoly() {
// 父类引用指向子类对象
// 同一个引用变量
// PolyFather polyFather;
//
// // 多态的效果
// polyFather = new FirstPolySon();
// // 父类引用指向FirstPolySon子类对象
// polyFather.testPolymorphism();
//
// polyFather = new SecondPolySon();
// // 父类引用指向SecondPolySon子类对象
// polyFather.testPolymorphism();
PolyFather polyFather = new PolyFather();
testPolyMorphism(polyFather);
PolyFather firstPolySon = new FirstPolySon();
testPolyMorphism(firstPolySon);
PolyFather secondPolySon = new SecondPolySon();
testPolyMorphism(secondPolySon);
// 可以把一个子类类型的引用变量值 赋值 给父类类型的引用变量值
PolyFather father = secondPolySon;
}
/*
多态的效果
*/
public static void testPolyMorphism(PolyFather polyFather) {
polyFather.testPolymorphism();
}
}
class PolyFather {
int value = 100;
public void testPolymorphism() {
System.out.println("testPolymorphism in father ");
}
}
class FirstPolySon extends PolyFather {
int value = 200;
@Override
public void testPolymorphism() {
System.out.println("testPolymorphism in first son");
}
// 子类自己定义的方法,父类中未定义
public void son() { }
}
class SecondPolySon extends PolyFather {
int value = 300;
@Override
public void testPolymorphism() {
System.out.println("testPolymorphism in second son");
}
}