写点什么

Surpass Day——Java 多态、final 关键字、常量、package、import、访问控制权限修饰符

作者:胖虎不秃头
  • 2022 年 10 月 08 日
    河南
  • 本文字数:3029 字

    阅读完需:约 10 分钟

Surpass Day——Java 多态、final关键字、常量、package、import、访问控制权限修饰符

1、多态

1.1 关于 java 语言中多态语言机制:

1)Animal、Cat、Bird 三个类之间的关系:


Cat 继承 Animal; Bird 继承 Animal; Cat 和 Bird 之间没有任何继承关系;


2)向上转型(upcasting) 子类型——>父类型(自动转换)


  • 编译通过,运行一定可以


向下转型(downcasting) 父类型——>子类型(强制类型转换)【需要加强制类型转换符】


  • 编译通过,运行不一定通过,存在隐患


3)无论是向上转型还是向下转型,两者必须要有继承关系;


public class helloworld {    public static void main(String[] args) {        Animal a = new Animal();        a.move();                Bird b = new Bird();        b.move();                Animal a2 = new Bird();//1.1.1关于该语句的解读        a2.move();                //a2.eat(); //1.1.2关于该语句的解读        Bird c2 = (Bird)a2;        c2.eat();                Animal a3 = new Cat();        Bird c3 = (Bird)a3;//1.1.3关于该语句的解读         }}class Animal {    public void move() {        System.out.println("动物会跑");    }}class Bird extends Animal {    //重写父类中继承的方法    public void move() {        System.out.println("鸟会跑");    }    //这个方法不是从父类中继承过来的,是子类中特有的行为    public void eat() {        System.out.println("鸟吃虫");    }}
复制代码


点击并拖拽以移动


1.1.1 关于 Animal a2 = new Bird();


1)java 程序分为编译阶段和运行阶段,编译不通过,是根本无法运行的


2)编译阶段,编译器检查 a2 这个引用的数据类型为 Animal,由于 Animal.class 字节码文件当中有 move()方法,所以编译通过了。这个过程我们称为静态绑定,编译阶段绑定,只有静态绑定成功之后才有后续的运行;


3)程序运行阶段,JVM 堆内存当中真实创建的对象是 Bird 对象,那么以下程序在运行阶段一定会调用 Bird 对象的 move 方法,此时发生程序的动态绑定,运行阶段绑定;


4)无论是 Bird 类有没有重写 move 方法,运行阶段一定调用的是 Bird 对象的 move 方法,因为底层真实的对象就是 Bird 对象


5)父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定运行阶段绑定的两种不同形态这种机制可以成为一种多态语法机制;


1.1.2 关于 a2.eat();


1)不能调用的原因: 因为编译阶段编译器检查到 a2 的类型是 Animal 类型,从 Animal.class 字节码文件当中查找 eat()方法,最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是编译失败,别谈运行了;


2)如何调用 a2.eat?


a2 是无法直接调用的,因为 a2 的类型的 Animal,Animal 中没有 eat()方法,想要调用,必须将 a2 强制转换成 Bird 类型,a2 的类型是 animal(父类),转换成 BIrd 类型(子类),需要向下转型,被称为向下转型(强制类型转换),需要加强制类型转换符;


向下转型的使用时刻:


当父类中没有子类的特有的方法,必须使用向下转型


1.1.3 关于 Bird c3 = (Bird)a3;


1)编译是没有问题的,因为编译器检查到 a3 的数据类型是 Animal,Animal 和 Bird 之间存在继承关系,并且 Animal 是父类型,Bird 是子类型,父类型转换成子类型叫做向下转型,语法合格;


2)程序虽然通过了,但是程序在运行阶段会出现异常,因为 JVM 堆内存当中真实存在的对象是 Cat 类型,Cat 类型无法转换成 Bird 对象,两种对象之间不存在继承关系,此时出现了著名的异常 java.lang.classCatexception,类型转换异常,这种异常总是在"向下转型"的时候发生;

1.2 instanceof

使用 instanceof 可以避免向下转型出现的 java.lang.classCatexception


1)语法格式:


(引用 instanceof 数据类型名)


2)运算符的执行结果是布尔类型,结果可能是 true/false


3)关于运算结果(true/false)


假设:(a instanceof Animal)//a 的实例化是动物吗?


true 表示 a 这个引用指向的对象是 Animal 类型


false 表示 a 这个引用指向的对象不是 Animal 类型


if(a3 instanceof Cat){    Cat c3 = (Cat)a3;    c3.catchMouse();}eles if(a3 instanceof Bird){    Bird b2 = (Bird)a3;}
复制代码


点击并拖拽以移动

1.3 多态语法的作用

1)降低程序的耦合度,提高程序的扩展力


2)能使用多态尽量使用多态


3)父类型引用指向子类型对象


public class helloworld {    public static void main(String[] args) {        Master zhangsan = new Master();//      Cat tom = new Cat();//      Dog amy = new Dog();//      zhangsan.feed(tom);//      zhangsan.feed(amy);        zhangsan.feed(new Cat());//上面四行代码和这两行实现的功能相同        zhangsan.feed(new Dog());        //new 具体宠物对象的形参传到Pet pet中        //相当于Pet pet = new Dog();     }}class Master {    public void feed(Pet pet) {//Pet pet是一个父类型的引用        pet.eat();    }}class Cat extends Pet{    public void eat() {        System.out.println("猫吃鱼!");    }}class Dog extends Pet{    public void eat() {        System.out.println("狗吃肉!");    }}class Pet {    public void eat() {    }}
复制代码


点击并拖拽以移动

2、final 关键字

表示:最终的,不可变的


  • final 修饰的类无法被继承

  • final 修饰的方法无法被覆盖

  • final 修饰的变量不可二次赋值

  • final 修饰的实例变量必须手动赋值,不能采用系统默认值;


//方法一:final int age = 10;//方法二:final int age;public Text(){    this.age = 10;}//其实本质上是一种方式,都是在构造方法中给实例变量赋值
复制代码


点击并拖拽以移动


  • final 修饰的引用

  • 1)一旦指向某个对象后,不能指向别的对象,被指向的对象不能被垃圾回收器回收;

  • 2)虽然指向某个对象后不能指向别的对象,但是所指的对象的内存是可以被修改的


final User user = new User(30);user = new User(5);//一旦指向某个对象后,不能指向别的对象user.id = 50;//内存可以被修改
复制代码


点击并拖拽以移动

3、常量

1) final 修饰的实例变量一般和 static 联合使用,称为常量


2)java 规范中要求所有变量的单词全部大写,每个单词之间使用下划线连接;


public static final String GUO_JI = "中国";


public static final double PI = 3.1415926;

4、package

1)引入包这个机制为了方便程序的管理,不同的功能的类被分门别类放到不同的软件包中,查找比较方便,管理比较方便,易维护;


2)在 java 源程序的第一行上编写 package 语句,package 只能编写一个语句;


3)语法结构: package 包名;


4)包名的命名规范: 公司域名倒叙 + 项目 + 模块名 + 功能名; e.g. com.bjpowernode.oa.user.service;(company) org.apache.tomcat.core;(orgnization)


5)包名要求全部小写,包名也是标识符,必须遵循标识符命名规范;


6)一个包将来对应的是一个目录;


7)使用 package 机制之后,类名是:包名.类名

5、import

1)import 语句用来导入其他类,同一个包下的类不需要导入


2) import 语法格式 import 类名; import 包名.*;


3)import 语句需要编写在 package 语句之下,class 语句之上;


*java.lang.不需要手动引入,系统自动引入;


lang:language 语言包,是 java 语言的核心类


String(java.lang.String)


4)eclipse 导入类的快捷键 Ctr + Shift + o

6、访问控制权限修饰符

1)作用:控制元素的访问范围


2)访问控制权限修饰符包括: public 表示公开的, 在任何位置都可以访问; protected 表示受保护的,在同包下、子类可以访问 default(缺省) 不写 在同包下可以访问 private 表示私有的, 在本类中访问;【内部类除外】


3)修饰符范围: private < 缺省 < protected < public


发布于: 刚刚阅读数: 5
用户头像

还未添加个人签名 2022.07.29 加入

还未添加个人简介

评论

发布
暂无评论
Surpass Day——Java 多态、final关键字、常量、package、import、访问控制权限修饰符_Java_胖虎不秃头_InfoQ写作社区