1. final 关键字特点
- final可以修饰类,该类不能被继承。
- final可以修饰方法,该方法不能被重写。
- final可以修饰变量,该变量不能被重新赋值。因为这个变量其实是常量。
- 常量:
A. 字面值常量 : “hello” , 10 , true
B. 自定义常量 : final int x = 10 ;
2. final 修饰局部变量的问题
- 基本类型:基本类型的值不能发生改变。
- 引用类型:引用类型的地址值不能发生改变。但是,该对象的堆内存的值是可以改变的。
class Student {
int age = 10;
}
class FinalTest {
public static void main(String[] args) {
int x = 10;
x = 100;
System.out.println(x);
final int y = 10;
// y = 100; 此行为错误,不能改变final关键字修饰的基本变量的值。
System.out.println(y);
System.out.println("--------------");
Student s = new Student();
System.out.println(s.age);
s.age = 100;
System.out.println(s.age);
System.out.println("--------------");
final Student ss = new Student();
System.out.println(ss.age);
ss.age = 100;
System.out.println(ss.age);
// ss = new Student(); 此行为错误,因为改变了final引用类型的地址值。
}
}
3. final 修饰变量的初始化时机
-
a. 只能初始化一次。
-
b. 常见的给值 :
定义的时候。(推荐)
构造方法中。
4. 多态的概述和前提条件
-
多态:同一个对象(事物),在不同时刻体现出来的不同状态。
-
多态的前提:
A. 有继承或者实现关系。
B. 有方法重写。
C. 有父类或者父接口引用指向子类对象。
5. 多态中的成员访问特点
- A. 成员变量 : 编译看左边,运行看左边
- B. 构造方法 : 子类的构造都会默认访问父类构造
- C. 成员方法 : 编译看左边,运行看右边
- D. 静态方法 : 编译看左边,运行看左边
- 为什么 ? 因为成员方法有重写。
class Fu {
public int num = 100;
public void show() {
System.out.println("show Fu");
}
public static void function() {
System.out.println("function Fu");
}
}
class Zi extends Fu {
public int num = 1000;
public int num2 = 200;
public void show() {
System.out.println("show Zi");
}
public void method() {
System.out.println("method zi");
}
public static void function() {
System.out.println("function Zi");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);
//System.out.println(f.num2);
f.show();
//f.method();
f.function();
}
}
上述代码的运行结果为:
100
show Zi
function Fu
6. 多态中向上转型和向下转型
- 向上转型:Fu f = new Zi( );
- 向下转型:Zi z = (Zi)f; // 要求该f必须是能够转换为Zi的。
class Fu {
public void show() {
System.out.println("show fu");
}
}
class Zi extends Fu {
public void show() {
System.out.println("show zi");
}
public void method() {
System.out.println("method zi");
}
}
class DuoTaiDemo4 {
public static void main(String[] args) {
Fu f = new Zi();
f.show();
//f.method();
//Zi z = new Zi();
//z.show();
//z.method();
Zi z = (Zi)f;
z.show();
z.method();
}
}
上述代码的运行结果为:
show zi
show zi
method zi
7. 猫狗案例多态版
class Animal {
public void eat(){
System.out.println("吃饭");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void lookDoor() {
System.out.println("狗看门");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame() {
System.out.println("猫捉迷藏");
}
}
class DuoTaiTest {
public static void main(String[] args) {
//定义为狗
Animal a = new Dog();
a.eat();
System.out.println("--------------");
//还原成狗
Dog d = (Dog)a;
d.eat();
d.lookDoor();
System.out.println("--------------");
//变成猫
a = new Cat();
a.eat();
System.out.println("--------------");
//还原成猫
Cat c = (Cat)a;
c.eat();
c.playGame();
System.out.println("--------------");
//演示错误案例
//Dog dd = new Animal();
//Dog ddd = new Cat();
//ClassCastException
// Dog dd = (Dog)a;
}
}
上述代码运行结果为:
狗吃肉
--------------
狗吃肉
狗看门
--------------
猫吃鱼
--------------
猫吃鱼
猫捉迷藏
--------------
8. 南北方人多态案例
class Person {
public void eat() {
System.out.println("吃饭");
}
}
class SouthPerson extends Person {
// public void eat() {
// System.out.println("炒菜,吃米饭");
// }
public void jingShang() {
System.out.println("经商");
}
}
class NorthPerson extends Person {
public void eat() {
System.out.println("炖菜,吃煎饼果子");
}
public void yanJiu() {
System.out.println("研究");
}
}
class DuoTaiTest2 {
public static void main(String[] args) {
Person p = new SouthPerson();
p.eat();
System.out.println("-------------");
SouthPerson sp = (SouthPerson)p;
sp.eat();
sp.jingShang();
System.out.println("-------------");
p = new NorthPerson();
p.eat();
System.out.println("-------------");
NorthPerson np = (NorthPerson)p;
np.eat();
np.yanJiu();
}
}
上述代码的运行结果为:
吃饭
-------------
吃饭
经商
-------------
炖菜,吃煎饼果子
-------------
炖菜,吃煎饼果子
研究
9. 多态练习题看程序写结果
-
A. 多态的成员访问特点:编译看左边,运行看右边。
-
B. 继承的时候:
子类中有和父类中一样的方法,叫重写。
子类中没有父类中出现过的方法,直接继承过来。
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
/*
public void show() { 因为B类没有show()方法,所以直接继承父类A的show()方法。
show2();
}
*/
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show();
B b = new C();
b.show();
}
}
上述程序的运行结果为:
爱
你
10. 抽象类的概念和特点
-
概念:
把多个共性的东西提取到一个类中,这是继承的做法。
但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体不一样。
也就是说,方法声明一样,但是每个具体的对象在具体实现的时候内容不一样。比如猫和狗的吃饭功能都继承自动物类,但是猫吃鱼,狗啃骨头。
所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体。
而一个没有具体的方法体的方法是抽象的方法。
在一个类中如果有抽象方法,该类必须定义为抽象类。
-
特点:
-
A. 抽象类和抽象方法必须用关键字abstract修饰
-
B. 抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
-
C. 抽象类不能实例化
-
D. 抽象类的子类
a. 是一个抽象类。
b. 是一个具体类。这个类必须重写抽象类中的所有抽象方法。
11. 抽象类的成员特点
-
A. 成员变量 : 有变量,有常量
-
B. 构造方法 : 有构造方法
-
C. 成员方法 : 有抽象,有非抽象
-
D. 成员方法的特性:
a. 抽象方法 强制要求子类做的事情。若父类中有抽象方法,则子类中必须写一模一样的方法。
b. 非抽象方法 子类继承的事情,提高代码复用性。
abstract class Animal {
public int num = 10;
public final int num2 = 20;
public Animal() {}
public Animal(String name,int age){}
public abstract void show(); // 继承它的子类中必须写public void show()方法
public void method() {
System.out.println("method");
}
}
class Dog extends Animal {
public void show() {
System.out.println("show Dog");
}
}
class AbstractDemo2 {
public static void main(String[] args) {
Animal a = new Dog();
a.num = 100;
System.out.println(a.num);
//a.num2 = 200; 此处为错误,因为num2 关键字“final” 相当于常量
System.out.println(a.num2);
System.out.println("--------------");
a.show();
a.method();
}
}
12. 抽象类练习员工案例
abstract class Employee {
private String name;
private String id;
private int salary;
public Employee() {}
public Employee(String name,String id,int salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public abstract void work();
}
class Programmer extends Employee {
public Programmer(){}
public Programmer(String name,String id,int salary) {
super(name,id,salary);
}
public void work() {
System.out.println("完成经理部署的任务");
}
}
class Manager extends Employee {
private int money;
public Manager(){}
public Manager(String name,String id,int salary,int money) {
super(name,id,salary);
this.money = money;
}
public void work() {
System.out.println("安排普通成员的工作");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
class AbstractTest4 {
public static void main(String[] args) {
Employee emp = new Programmer();
emp.setName("徐康健");
emp.setId("xkj91354");
emp.setSalary(8000);
System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
emp.work();
System.out.println("-------------");
emp = new Programmer("高晗","hanxue899",18000);
System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
emp.work();
System.out.println("-------------");
// emp = new Manager();
// emp.setName("带带大师兄");
// emp.setId("cxk002");
// emp.setSalary(8000);
// emp.setMoney(2000);
Manager m = new Manager();
m.setName("杨腾宇");
m.setId("yty6352184");
m.setSalary(80000);
m.setMoney(20000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
m.work();
System.out.println("-------------");
// 用构造方法赋值
m = new Manager("杨博雯","yty5537238",81000,24000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
m.work();
}
}