Java基础Day10

day10

  1. final关键字
    final : 关键字,表示最后的,最终的,不可改变的
    final: 修饰符
  2. final 可以修饰类 : 不能被继承,不能当父类,但是类本身可以正常的创建对象使用

代码
// 定义一个使用final修饰的类: 不能当父类,不能被继承
public final class FinalClass {
public static void main(String[] args) {
System.out.println(“Hello World!”);
}
}

// final修饰的类的子类,报错了,FinalClass是final修饰的
// final修饰的类不能被继承
public class FinalClassSub extends FinalClass{

}

  1. final 可以修饰变量 : final修饰的变量,只能手动的赋值一次,再也不能修改了,通常情况下,都是使用final修饰成员变量
    举例 : π参数,值固定 3.1415926…
    π实际定义在Math类中,是一个使用final修饰的变量 final double π = 3.14…
    说明 : final修饰的变量,称为常量

final修饰的成员变量的赋值时机:

  1. 定义就直接赋值,最推荐
  2. 构造方法中赋值

代码
// 验证final修饰的变量和方法的特点
public class FinalDemo {
int i = 10 ;
// 1) 定义就直接赋值 ,最推荐的赋值方式
final int j = 99 ;
// final修饰的成员变量,必须在创建对象完成之前,进行赋值
// new 完成之前
final int z ;
//final修饰的成员变量在构造方法中赋值
public FinalDemo(){
z = 100;
}

public static void main(String[] args) {
	FinalDemo fd = new FinalDemo();
	fd.i = 88 ;
	// final修饰的变量,数值不能修改,final修饰的变量,只能有一次手动赋值
	// fd.j = 999 ;
	System.out.println(fd.i);
	System.out.println(fd.j);
	System.out.println(fd.z);

}

}

  1. final 可以修饰方法 : 这个方法不能被重写(子父类继承关系中,子类重写父类中的方法)

代码

// 验证final修饰的变量和方法的特点
public class FinalDemo {
int i = 10 ;
// 定义就直接赋值 ,最推荐的赋值方式
final int j = 99 ;
final int z ;

public FinalDemo(){
    z = 100;
}

// 定义一个使用final修饰的方法
public final void finalMethod(){
   System.out.println("我是一个final修饰的方法");
}

}

public class FinalDemoSub extends FinalDemo{
// 从父类FinalDemo中继承到了 i , j ,z 变量
// 继承到了finalMethod 方法
/*
错误代码,父类中使用final修饰的finalMethod方法
不能被子类重写

@Override
public final void finalMethod(){
   System.out.println("我是一个final修饰的方法的子类重写");
}*/

public static void main(String[] args) {
    FinalDemoSub  f = new FinalDemoSub();
	// 子类继承使用父类中final成员
	System.out.println(f.i);
	System.out.println(f.j);
	System.out.println(f.z);
	f.finalMethod();
}

}

  1. 多态
    多态是面向对象一大特征
    2.1 多态的概念
    多态 : 表示事物的多种形态
    举例 : 人类,Person类
    人类的表现方式,工程师,医生,学生,…
    Animal 动物,cat,dog,鳄鱼,蛇…

多态的定义:

  1. 具有子父类的继承关系
  2. 需要子类重写父类方法
  3. 父类的引用指向子类的对象

代码
// 定义一个父类Person
public class Person {
public void work(){
System.out.println(“人类需要工作”);
}
}

// 定义一个工程师类,继承人类,因为工程师也是人类的一种
public class Employee extends Person{
@Override
public void work(){
System.out.println(“工程师开发代码”);
}
}

// 医生类继承Person类,因为医生也是人类的一种表现形式
public class Doctor extends Person{
public void work(){
System.out.println(“医生治病求人”);
}
}

public class TestPerson{
public static void main(String[] args) {
// 多态 : 父类的引用指向子类的对象
// Person p----> 父类的引用
// new Employee ----> 子类对象
Person p = new Employee();
p.work();// 工程师开发代码

	// 创建一个医生对象
	Doctor d = new Doctor();
	//多态
    Person p1 = new Doctor();
	p1.work(); // 医生治病求人
}

}

2.2 多态中成员变量的访问特点
编译看等号左边,运行等号左边的变量(成员变量严格意义上,不玩多态)
编译 : 执行javac命令的时候,是否报错,写代码时
运行 : 执行java命令的时候

  1. 编译看左边 : 表示如果父类中没有定义这个变量,那么在类中使用这个变量,写出来就会报错
  2. 运行看左边: 变量的运行结果,与等号左边的类中定义的变量中保持一致

代码
// 定义一个父类
public class Fu{
int a = 10;
int b = 15;
}

// 定义子类,继承父类
public class Zi extends Fu {
// 1. 子类从父类中继承到了变量 a , b
int c = 99 ;

 // 2. 定义一个与父类相同的变量
 int a = 999;

}

// 测试多态的访问特征
public class TestFu{
public static void main(String[] args) {
// 1. 验证多态成员变量在多态中访问特点
Fu f = new Zi();
// 多态中,成员变量编译和运行看等号左边的类
System.out.println(f.a);// 10
System.out.println(f.b);// 15

	Zi z = new Zi();
	System.out.println(z.a);// 999
	System.out.println(z.b);// 15

	// 子类特有的成员变量c,因为Fu类中,没有定义c变量
	// System.out.println(f.c);  不能运行。
}

}

2.3多态中方法的访问特点
编译看左边,运行看右边(子类重写)----> 这是多态的表体现方式

  1. 编译看左边 : 如果父类中,没有定义这个方法,那么无法通过多态调用到这个方法,因此编译错误
  2. 运行看右边 : 方法运行时,运行的子类中的重写方法

代码
// 定义一个父类
public class Fu{
public void eat(){
}
}

// 定义子类,继承父类
public class Zi extends Fu {
// 1. 重写父类中的eat方法
@Override
public void eat(){
System.out.println(“一会去吃饭”);
}

 // 2.子类定义一个特有的功能
 public void sleep(){
    System.out.println("吃完饭,休息一会");
 }

}

// 测试多台的访问特征
public class TestFu{
public static void main(String[] args) {
Fu f = new Zi();
// 验证多态中方法的访问特点
f.eat();//调用子类重写方法
//f.sleep();// Fu类中没有定义sleep方法,那么会报出编译错误
}
}

2.4多态中静态的访问特点
编译看左边,运行看左边

  1. 编译看左边 : 如果等号左边的类中,没有定义这个静态的成员(成员变量和方法),那么调用这个静态就会报错
  2. 运行看左边 : 代码调用的静态,根据等号左边类中定义的静态成员的运行结果为准

原因 : 静态属于类,不属于任何对象

代码
// 定义一个父类
public class Fu{
public static void speak(){
System.out.println(“父类的静态speak”);
}
}

// 定义子类,继承父类
public class Zi extends Fu {
// 子类中可以继承到父类中的静态方法 speak,子类自己重新定义了speak方法
public static void speak(){
System.out.println(“zi类的静态speak”);
}
}

// 测试多台态的访问特征
public class TestFu{
public static void main(String[] args) {
Fu f = new Zi();
// 3. 静态在多态中的访问特点,编译运行全看等号左边
f.speak();//父类的静态speak
}
}

2.5多态的转型

  1. 向上转型 : 父类的引用指向子类的对象,向上转型(变量f只能使用子父类同有的方法)
    Fu f = new Zi();
    实质 : 使用范围在缩小,子类中的特有的成员变量和方法,全部不能调用
    理解 : Zi年轻,Fu年长,年轻------>年长---->年龄增长,向上
  2. 向下转型
    要求: 在多态的使用场景下,想要使用子类中的特有的成员变量和方法
    通过多态的向下转型实现

公式: 将父类的引用最终还原成一个子类的类型
子类的类型 变量名 = (子类的类型)父类的引用;
Fu f = new Zi(); // 多态,向上转型
Zi z = (Zi)f;

代码
// 定义一个父类Person
public class Person {
public void work(){
System.out.println(“人类需要工作”);
}
}

// 医生类继承Person类,因为医生也是人类的一种表现形式
public class Doctor extends Person{
public void work(){
System.out.println(“医生治病求人”);
}
// 医生这个子类的特有方法,在父类Person中没有的
public void study(){
System.out.println(“医生需要学习”);
}
}

public class TestPerson{
public static void main(String[] args) {
// 创建一个医生对象
Doctor d = new Doctor();
//多态
Person p1 = new Doctor();
p1.work(); // 医生治病求人

	// 使用多态的向下转型 : 可以调用子类中特有的变量和方法
    Doctor doc = (Doctor)p1;
	doc.study();
}

}

2.6多态的好处和使用
封装 : 好处,安全性高,复用性
继承 : 复用性,可维护性
多态 : 扩展性

多态扩展性的使用场景 : 定义一个功能,将功能的参数类型,设定为一个父类的类型,这个功能在实际调用的时候,父类的本身以及该父类的所有的子类,都可以作为方法的实际参数进行传递

动物吃饭案例:
定义一个Animal类,动物都能吃
动物有子类 cat , dog
定义一个测试类,测试类中: 定义一个动物吃饭功能,要求不同的动物吃不同的饭

代码
public class Animal {
public void eat(){

}

}

public class cat extends Animal{
public void eat(){
System.out.println(“猫吃猫粮”);
}
}

public class dog extends Animal {
public void eat(){
System.out.println(“狗啃骨头”);
}
}

public class TestAnimal{
//定义一个方法,能让不同的动物,吃不同饭
public void animalEat(Animal a){// Animal a = new cat();
a.eat();
}
public static void main(String[] args) {
TestAnimal ta = new TestAnimal();
// 需要一个Animal类型的参数
Animal a = new cat();
ta.animalEat(a);//new cat();
Animal a1 = new dog();
ta.animalEat(a1);
}
}

榨汁机案例:
要求 : 定义一个榨汁机类,类中有一个方法,榨汁,榨汁功能,能榨苹果汁,也能榨橙汁,任何谁都可以榨汁

代码
// 水果类,可以作为所有类的父类
public class Fruit{
public void flow (){
System.out.println(“榨汁”);
}
}

// 定义一个水果,苹果
public class Apple extends Fruit{
@Override
public void flow (){
System.out.println(“苹果汁”);
}
}

// 定义一个水果,叫橙子
public class Orange extends Fruit{
@Override
public void flow(){
System.out.println(“橙子汁”);
}
}

// 定义一个榨汁机类
public class JuiceMachine{
// 如果将一个父类作为方法的参数
public void makeJuice(Fruit f){ // Fruit f = new Apple();
// 不同的水果,出不同的果汁
f.flow();
}

  public void getInt(int i){// int i = 9
  
  }

  /*public void makeJuice(Orange o){
     o.flow();
  }*/

  public static void main(String[] args) {
    JuiceMachine jm = new JuiceMachine();
	// makeJuice 方法需要一个参数,类型Fruit
	// 1.多态
    Fruit f = new Apple();
	jm.makeJuice(f);// 苹果汁 new Apple(); 
    Fruit f1 = new Orange();
	jm.makeJuice(f1);// 橙子汁

	// 2. 多态的应用
	Apple a = new Apple();
	jm.makeJuice(a);// 苹果汁 new Apple();
    // 需要int类型参数
	int i = 9 ;
	jm.getInt(i);//实际传值为9
  }

}

  1. 抽象类
    抽象 : 就是无法描述的
    3.1 抽象方法
    抽象方法 : 只有方法的声明,没有方法的实现主体

普通方法定义:
修饰符 返回值类型 方法名(参数列表){
// 方法逻辑
return ;
}

抽象方法的定义:
修饰符 abstract 返回值类型 方法名(参数列表) ; ----- > 抽象方法
abstract : 关键字,抽象的含义

在这里插入图片描述

代码
// 抽象的定义
public class AbstractDemo {
// 定义一个抽象方法
public abstract void eat();
}

3.2 抽象类
抽象方法需要存在于抽象类中
抽象类的定义:

修饰符 abstract class 类名{
// 可以定义抽象方法
}

代码
// 抽象的定义
public abstract class AbstractDemo {
// 定义一个抽象方法
public abstract void eat();
}

3.3抽象的特点

  1. 抽象方法和抽象类都使用abstract关键字修饰的
    public abstract void eat(); ---->抽象方法
    public abstract class 类名{}----->抽象类
  2. 抽象方法必须要存在于抽象类中
    抽象类中不一定含有抽象方法
  3. 抽象类不能实例化对象,new对象不行
  4. 抽象类和抽象方法存在的意义:
  1. 抽象类存在的意义,等着被继承,等着当父类
  2. 抽象方法存在的意义,等着被重写
  3. 抽象方法是可以被子类继承到的,抽象类的子类,如果没有将父类中的所有抽象方法全部重写,那么这个子类仍然是个抽象类
  4. 如果子类将父类中的所有抽象方法全部重写,这个子类及时一个普通的类,可以实例化对象,可以调用重写的方法

为什么要有抽象: 做规则的限定
例如 : Animal类,每个动物都需要吃饭,但是Animal不知道如何实现eat吃这个功能,Animal就将eat定义为抽象方法,Animal类就变成抽象类. 现在Animal的所有子类,必须吃饭,必须实现eat方法,才能成为一个正常的动物

代码
// 抽象的定义
public abstract class AbstractDemo {
// 定义一个抽象方法
public abstract void eat();

public static void main(String[] args) {
	// 抽象类不能实例化对象
	// 原因: 抽象类中,可能含有抽象方法,抽象方法因为没有方法体,
	// 不能运行
	// 如果抽象类可以实例化对象,那么就可以通过对象名.调用抽象方法运行
	// 抽象方法不能运行,矛盾了
	//AbstractDemo ad = new AbstractDemo();
}

}

// 抽象类AbstractDemo的子类
public class AbstractDemoSub extends AbstractDemo{
// AbstractDemoSub 继承了抽象父类AbstractDemo里面的抽象方法eat
public void eat(){
System.out.println(“子类重写了父类的抽象方法”);
}
public static void main(String[] args) {
AbstractDemoSub as = new AbstractDemoSub();
as.eat();
System.out.println(“Hello World!”);
}
}

3.4抽象方法的重写
public abstract void eat();
子类重写抽象方法的注意事项:

  1. abstract 抽象关键字,去掉
  2. 方法后面的; 去掉
  3. 给方法添加上方法体{}
    public void eat(){
    // 子类可以任意的实现重写方法内容
    System.out.println(“子类重写了父类的抽象方法”);
    }

3.5抽象类的成员
将抽象类先当成一个普通的类看待,只不过比普通的类可以多定义抽象方法

  1. 成员变量
  2. 构造方法 : 给成员变量赋值,通过什么鉴定一个文件是否可以定义构造
    看这个文件中能不能定义变量,如果可以定义成员变量,就可以具有构造方法
  3. 普通方法
  4. 静态方法 : 静态属于类,与对象无关
  5. 抽象方法

代码
// 抽象的定义
public abstract class AbstractDemo {
int i = 10 ;
// 定义一个抽象方法
public abstract void eat();

public static void sleep(){
  System.out.println("sleep");
}

public static void main(String[] args) {
	// 抽象类不能实例化对象
	// 原因: 抽象类中,可能含有抽象方法,抽象方法因为没有方法体,
	// 不能运行
	// 如果抽象类可以实例化对象,那么就可以通过对象名.调用抽象方法运行
	// 抽象方法不能运行,矛盾了
	//AbstractDemo ad = new AbstractDemo();
}

}

  1. 接口
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值