Java学习之路09

Java学习笔记09

final 关键字引入

  • 我们不想让子类去覆盖掉父类的功能(方法重写会覆盖掉父类的方法),只能让父类使用,这个时候,Java就提供了一个关键字:final
  • final:常见可以修饰类,方法,变量

final 关键字的特点

  • final可以修饰类,该类不能被继承
  • final可以修饰方法,该方法不能被重写
  • final可以修饰变量,该变量不能被重新赋值,因为这个变量其实是常量
  • 常量
  1. 字面值常量:"hello",10,true
  2. 自定义常量:final int x = 10
  • 代码示例:
//final class Fu//无法从最终Fu进行继承
class Fu {
    /*public final void show() {
        System.out.println("lhk");
    }
    */
    public int num = 10;
    public final int num2 = 20;
    public void show() {
        
    }
}

class Zi extends Fu {
    //Zi中的show()无法覆盖Fu中的show()
    public void show() {
        num = 100;
        //num2 = 200;
        System.out.println(num);
        System.out.println(num2);
    }
}
public class finalDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

final 关键字修饰局部变量

  • 修饰基本类型:基本类型的值不能发生改变
  • 修饰引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值(即类中的变量值)是可以改变的
  • 代码示例:
class Student {
    int age = 10;
}

public class FinalTest {
    public static void main(String[] args) {
        int x = 10;
        x = 100;
        System.out.println(x);
        
        final int y = 10;
        //无法为最终变量y分配值
        //y = 100;
        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);
        //final 修饰ss的地址值
        
        //重新分配内存空间给ss,这是不允许的
        //ss = new Student();
    }
}

final 修饰变量的初始化时机

  • 被final 修饰的变量只能赋值一次
  • 在构造方法完毕前(非静态的常量)

多态的概述和成员访问特点

  • 某一个对象,在不同时刻表现出来的不同状态
  • 多态的前提
  1. 要有继承关系或者实现关系
  2. 要有方法重写
  3. 要有父类或者父类接口引用指向子类对象
    父 f = new 子();
  • 多态的分类
  1. 具体类多态
    class Fu() {}
    class Zi extends Fu {}
    Fu f = new Zi();
  2. 抽象类多态
    abstract class Fu() {}
    class Zi extends Fu {}
    Fu f = new Zi();
  3. 接口多态
    interface Fu() {}
    class Zi implements Fu {}
    Fu f = new Zi();
  • 多态中的成员访问特点
  1. 成员变量
    编译看左边,运行看左边
  2. 构造方法
    创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化
  3. 成员方法(方法存在覆盖)
    编译看左边,运行看右边
  4. 静态方法
    编译看左边,运行看左边
    (静态和类相关,算不上重写,所以,访问还是左边的)
  5. 代码示例:
class Fu2 {
    public int num = 100;
    
    public void show() {
        System.out.println("show Fu2");
    }
    public static void function() {
        System.out.println("function Fu2");
    }
    
}

class Zi2 extends Fu2 {
    public int num = 1000;
    public int num2 = 100;
    
    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");
    }
}

public class DuotaiDemo {
    public static void main(String[] args) {
        Fu2 fu = new Zi2();
        System.out.println(fu.num);
        //System.out.println(fu.num2);
        fu.show();
        //fu.method();
        fu.function();
    }
}

多态的好处

  • 提高了代码的维护性(继承保证)
  • 提高了代码的扩展性(由多态保证)
  • 代码示例:

class Animal {
    public void eat() {
        System.out.println("eat");
    }
    
    public void sleep() {
        System.out.println("sleep");
    }
}

class Dog extends Animal {
    public void eat() {
        System.out.println("eat bone");
    }
    
    public void sleep() {
        System.out.println("Dog sleep");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("eat fish");
    }
    
    public void sleep() {
        System.out.println("Cat sleep");
    }
}

class Pig extends Animal {
    public void eat() {
        System.out.println("eat fruit");
    }
    
    public void sleep() {
        System.out.println("Pig sleep");
    }
}

//针对动物类操作的工具书
class AnimalTool {
    //让使用者无法创建对象
    /*
    private AnimalTool() {      
    }
    //调用猫的功能
    public static void useCat(Cat cat) {
        cat.eat();
        cat.sleep();
    }
    //调用狗的功能
    public static void useDog(Dog dog) {
        dog.eat();
        dog.sleep();
    }
    //调用猪的功能
    public static void usePig(Pig pig) {
        pig.eat();
        pig.sleep();
    }
    */  
    public static void useAnimal(Animal a) {
        a.eat();
        a.sleep();
    }
}

public class DuotaiDemo2 {
    public static void main(String[] args) {
        //喜欢猫
        Cat cat = new Cat();
        cat.eat();
        cat.sleep();
        
        //超喜欢猫
        Cat cat2 = new Cat();
        cat2.eat();
        cat2.sleep();
        System.out.println("------");
        //改进版本
        //useCat(cat);
        //useCat(cat2);
        //AnimalTool.useCat(cat);
        //AnimalTool.useCat(cat2);
        AnimalTool.useAnimal(cat);
        AnimalTool.useAnimal(cat2);
        System.out.println("------");
        //我喜欢狗
        Dog dog = new Dog();
        Dog dog2 = new Dog();
        //AnimalTool.useDog(dog);
        //AnimalTool.useDog(dog2);
        AnimalTool.useAnimal(dog);
        AnimalTool.useAnimal(dog2);
        System.out.println("------");
        //我喜欢猪
        Pig pig = new Pig();
        Pig pig2 = new Pig();
        //AnimalTool.usePig(pig);
        //AnimalTool.usePig(pig2);
        AnimalTool.useAnimal(pig);
        AnimalTool.useAnimal(pig2);
        System.out.println("------");
        //我喜欢的动物还有很多
        //但我们必须写一个方法去代替重复构造动物功能的过程      
    }
}

多态的弊端和解决方法

  • 父不能使用子类的特有功能
  • 我们要解决这个问题:多态中向上转型和向下转型
  1. 向上转型:Fu f = new Zi();
  2. 向下转型:Zi z = (Zi)f;//要求该f必须是能够转换为Zi的
  3. 代码示例:
class Fu3 {
    public void show() {
        System.out.println("show Fu3");
    }
}

class Zi3 extends Fu3 {
    public void show() {
        System.out.println("show Zi3");
    }
    
    public void method() {
        System.out.println("method Zi3");
    }
}
public class DuotaiDemo3 {
    public static void main(String[] args) {    
        Fu3 fu3 = new Zi3();
        fu3.show();
        //fu.method();
        //我们能够把子的对象赋值给父亲,那能否把父的引用赋值给子的引用呢?
        Zi3 zi3 = (Zi3)fu3;//向下转型
        zi3.show();
        zi3.method();
    }
}

多态中的内存图解

  • 多态继承中的内存图解
  • [图片上传失败...(image-39fa80-1510752835050)]
  • 多态中的对象变化内存图解
  • [图片上传失败...(image-340db8-1510752835050)]

多态基本案例

  • 代码示例:
class Animal2 {
    public void eat() {
        System.out.println("eat");
    }
}

class Dog2 extends Animal2 {
    public void eat() {
        System.out.println("bone");
    }
    
    public void lookDoor() {
        System.out.println("lookDoor");
    }
}

class Cat2 extends Animal2 {
    public void eat() {
        System.out.println("fish");
    }
    
    public void playGame() {
        System.out.println("sweater");
    }
}
public class DuotaiTest {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        Animal2 animal = new Dog2();
        animal.eat();
        System.out.println("-------");
        //还原成狗
        Dog2 d = (Dog2)animal;
        d.eat();
        d.lookDoor();
        System.out.println("-------");
        //变成猫
        animal = new Cat2();
        animal.eat();
        System.out.println("-------");
        //还原成猫
        Cat2 cat = (Cat2)animal;
        cat.eat();
        cat.playGame();
        System.out.println("-------");
    }
}

抽象类的概述

  • 在Java 中,我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类

抽象类的特点

  • 格式:
  1. 抽象类和抽象方法必须用abstract 关键字修饰
  2. 抽象类中不一定有抽象方法,但是有抽象方法的类
  3. 抽象类不能实例化(抽象类有构造方法,但是不能实例化,构造方法用于子类访问父类数据的初始化)
  4. 抽象的子类
    a. 如果不想重写抽象方法,该子类是一个抽象类
    b. 重写所有的抽象方法,这时候子类是一个具体的类
  • 抽象类的实例化其实是靠具体的子类实现的,是多态的方式
  • 代码示例:
abstract class Animal4 {
    //抽象方法
    //public abstract void eat() {}//空方法体,报错
    public abstract void eat();//没有方法体
}

//子类是抽象类
abstract class Dog4 extends Animal4 {}

//子类是具体类,重写抽象方法
class Cat4 extends Animal4 {
    public void eat() {
        System.out.println("eat fish");
    }
}

public class ChouxiangDemo {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        //通过多态的方法
        Animal4 animal4 = new Cat4();
        animal4.eat();
    }
}

抽象类的成员特点

  • 成员变量:既可以是变量,也可以是常量
  • 构造方法:有,用于子类访问父类数据的初始化
  • 成员方法:既可以是抽象的,也可以是非抽象的
  • 抽象类的成员方法特征
  1. 抽象方法:强制要求子类做的事情
  2. 非抽象方法,子类继承的事情,提高代码的复用性
  • 代码示例:
abstract class Animal5 {
    public int num = 10;
    
    public Animal5() {}
    
    public Animal5(String name,int age) {}
    
    public abstract void show();
    
    public void method() {
        System.out.println("show method");
    }
}

class Dog5 extends Animal5 {
    public void show() {
        System.out.println("show Dog5");
    }
}
public class AbstractDemo {
    public static void main(String[] args) {
        Animal5 animal5 = new Dog5();
        System.out.println(animal5.num);
        System.out.println("------");
        animal5.show();
        animal5.method();
    }
}

示例代码

//定义员工类
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("code");
    }
}

//经理
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("communicate");
    }
    
    public int getMoney() {
        return money;
    }
    
    public void setMoney(int money) {
        this.money = money;
    }
}
public class AbstractTestDemo3 {
    public static void main(String[] args) {
        //测试普通员工
        Employee employee = new programmer();
        employee.setName("lhk");
        employee.setid("hk");
        employee.setSalary(1000000000);
        System.out.println(employee.getName() + "---" + employee.getid() + "---" + employee.getSalary());
        System.out.println("-------");
        employee = new programmer("lhk","nihao",10000);
        System.out.println(employee.getName() + "---" + employee.getid() + "---" + employee.getSalary());
        System.out.println("-------");
        /*
        employee = new manager();
        employee.setName("lhk");
        employee.setid("hk");
        employee.setSalary(2000000000);
        employee.setmoney(3151345);
        */
        //由于子类特有的内容,所以我们用子类来测试
        manager manager = new manager();
        manager.setName("lhk");
        manager.setid("hk");
        manager.setSalary(2000000000);
        manager.setMoney(3151345);
        System.out.println(manager.getName() + "---" + manager.getid() + "---" + manager.getSalary() + "---" + manager.getMoney());
        manager.work();
        System.out.println("-------");
        //通过构造方法赋值
        manager = new manager("lhk","hk",66666,352354);
        System.out.println(manager.getName() + "---" + manager.getid() + "---" + manager.getSalary() + "---" + manager.getMoney());
        manager.work();
    }
}

抽象类中的小问题

  • 一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
  1. 可以
  2. 不让外界创建对象
  • abstract 不能和哪些关键字共存
  1. private 冲突

建立抽象方法的目的是让子类去重写这个方法,而一旦加了private,子类就不能进行重写了,无意义

  1. final 冲突

同理,子类不能进行方法重写

  1. static 无意义
  2. 代码示例:
abstract class Fu6 {
    //public abstract void show();
    //非法的修饰符组合:abstract和private
    //private abstract void show();
    //非法的修饰符组合
    //final abstract void show();
    //show方法没有方法体,访问一个没有方法体的方法,无意义
    //static abstract void show();
    
    public static void method() {
        System.out.println("method");
    }
}

class Z6 extends Fu6 {
    public void show() {        
    }
}
public class XiaoWenTiDemo {
    public static void main(String[] args) {
        Fu6.method();
    }
}

接口的成员特点

  • 成员变量:只能是常量,并且是静态的
    默认修饰符:public static final
    建议手动给出
  • 构造方法:接口没有构造方法
  • 成员方法:只能是抽象方法
    默认修饰符:public abstract
    建议手动给出
  • 所有的类都默认继承自一个类:Object
    类Object 是类层次结构的根类,每个类都使用Object 作为超类
  • 代码示例:
interface Inter {
    public int num = 10;
    public final int num2 = 20;
    //完整版中的接口变量
    public static final int num3 = 30;
    //public Inter() {}
    
    //接口方法不能带有主体
    //public void show() {}
    
    //abstract void show();默认是public
    public void show();//默认是abstract
}
//接口名+Impl这种格式是接口的实现类格式
//class InterImpl extends Object implements Inter {}
class InterImpl implements Inter {
    public InterImpl() {
        super();
    }
    
    public void show() {
        
    }
}
public class InterfaceDemo {
    public static void main(String[] args) {
        Inter inter = new InterImpl();
        System.out.println(inter.num);
        System.out.println(inter.num2);
        //inter.num = 199;
        //无法为num或者num2分配值,因为接口中默认num已为常量
        //和final效果一样
        System.out.println("------");
        System.out.println(Inter.num);
        System.out.println(Inter.num2);
        
    }
}

类与类,类与接口,接口与接口的关系

  • 类与类
  1. 继承关系:只能单继承,但是可以多层继承
  • 类与接口
  1. 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口与接口
  1. 继承关系,可以单继承,也可以多继承
  • 代码示例;
package exp2.demo;
/*
 * 类与类:继承关系:只能单继承,但是可以多层继承
 * 类与接口:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
 * 接口与接口:继承关系,可以单继承,也可以多继承
 */

interface Father {
    public void show();
}

interface Mother {
    public abstract void show2();
    
}

interface Sister extends Father,Mother {
    
}
//class Son implement Father,Mother //多实现
//还可以在继承一个类的同时实现多个接口
class Son extends Object implements Father,Mother{
    public void show() {
        System.out.println("show son");
    }
    
    public void show2() {
        System.out.println("show2 son");
    }
}
public class AbstractDemo {
    public static void main(String[] args) {
        Father father = new Son();
        father.show();
        //father.show2();
        Mother mother = new Son();
        mother.show2();
        //mother.show();
    }
}

抽象类和接口的区别

  • 成员区别
  1. 抽象类:
    成员方法:可以变量,也可以常量
    构造方法:有
    成员方法:可以抽象,也可以非抽象
  2. 接口:
    成员变量:只可以常量
    成员方法:只可以抽象
  • 关系区别
  1. 类与类:继承,单继承
  2. 类与接口:实现,单继承,多实现
  3. 接口与接口:继承,单继承,多继承
  • 设计理念区别
  1. 抽象类:被继承体现的是:“is a”的关系,抽象类中定义的是该继承体现的共性功能
  2. 接口:被实现体现的是:“like a”的关系,接口中定义的是该继承体系的扩展功能

跳高猫代码示例

package exp2.demo;
//定义跳高接口
interface Jumpping {
    public abstract void jump();
}

//定义抽象类
abstract class Animal {
    private String name;
    private int age;
    
    public Animal() {};
    
    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    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 abstract void eat();
    //睡觉
    public void sleep() {
        System.out.println("sleep");
    }
} 

class Dog extends Animal {
    public Dog() {}
    
    public Dog(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("eat bone");
    }
}

class Cat extends Animal {
    public Cat() {}
    
    public Cat(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("eat fish");
    }
}

//跳高猫
class JumpCat extends Cat implements Jumpping {
    public JumpCat() {}
    
    public JumpCat(String name,int age) {
        super(name,age);
    }
    public void jump() {
        System.out.println("jump cat");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        //定义跳高猫
        JumpCat jumpCat = new JumpCat();
        jumpCat.setName("nihao");
        jumpCat.setAge(20);
        System.out.println(jumpCat.getName() + jumpCat.getAge());
        jumpCat.eat();
        jumpCat.sleep();
        jumpCat.jump();
        System.out.println("------");
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容

  • Win7下如何打开DOS控制台? a:开始--所有程序--附件--命令提示符 b:开始--搜索程序和文件--cmd...
    逍遥叹6阅读 1,595评论 4 12
  • [TOC] final 关键字 final关键字,可以修饰类,成员变量,成员方法。 特点:修饰的类,类不能被继承修...
    lutianfei阅读 258评论 0 1
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,650评论 0 11
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,625评论 18 399
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 1,202评论 0 5