Java考试复习
2020-12-2
更新到 静态方法覆盖
好困, super那里的知识点看了好久, 终于大概弄懂啦hhhh
目录
多态
//向上/下转型: 之间必须有继承关系
class Animal{
public void move{...}
};
class Cat extends Animal{
public void move{.......}
public void catchMouse{....}
};
Animal a = new Cat();
//向上转型(自动转型) 父类引用 指向 子类型对象
//Cat is Animal
a.move();
//这里调用的是Cat中的move
//编译和运行能通过
a.catchMouse();
//编译不能通过
理 解:
Java 程序: 编译阶段 & 运行阶段
编译阶段:
- 编译器只知道a的类型是Animal
- 编译器检查语法时, 会去Animal.class字节码文件中 找到 move()
- 即是: 静态绑定成功
- 但是在Animal.class中 找不到 catchMouse()
- 即是: 静态绑定失败
运行阶段:
- 堆内存实际 创建的是Cat对象
- 真正参与move的对象是Cat
- 所以会 动态执行 Cat中的move方法
- 即是: 动态绑定
- 对于catchMouse 编译不能通过 就更不能运行啦
//多态: 编译的时候一种状态, 运行的时候一种状态
当需要访问子类对象中特有的方法——向下转型
Cat x = (Cat)a;
x.catchMouse();
//编译运行通过
instanceof
-
运行阶段 动态判断引用指向的对象类型
-
语法: 引用 instanceof 类型
-
向下转型时 , 使用instanceof 判断 , 避免 ClassCastException
if(a instanceof Cat){ Cat x = (Cat)a; x.catchMouse(); }
this
- 只能出现在实例方法和构造方法中
- 不能在静态方法中使用
- this() 只能出现在构造方法的第一行
super
- 只能出现在实例方法和构造方法中
- 不能在静态方法中使用
- super() 只能出现在构造方法的第一行
- 通过当前的构造方法调用父类的构造方法
- 目的: 创建子类对象的 时候. 先初始化父类特征
this() 和super() 不能在构造器中共存
代码理解1
class Father{
public Father(){
System.out.println("父类构造");
}
}
class Son extends Father{
public Son(){
/*
这里虽然什么都没写, 但是默认这里会有一个 super();
调用父类的无参构造√
*/
System.out.println("子类构造");
}
}
public class Test{
public static void main(String[] args){
new Son();
}
}
//输出:
//父类构造
//子类构造
代码理解2
class Father{
public Father(int i ){
System.out.println("父类构造");
}
}
class Son extends Father{
public Son(){
/*
这里虽然什么都没写, 但是默认这里会有一个 super();
但是 因为父类写了有参构造, 那么就没有了无参构造
所以 没法调用父类的无参构造
所以 最终报错
*/
System.out.println("子类构造");
}
}
public class Test{
public static void main(String[] args){
new Son();
//编译报错
}
}
代码理解3
好 一 个 套 娃 啊 (⊙o⊙)
package javastudy;
import java.util.logging.Level;
import java.util.logging.Logger;
class A{
public A(){
System.out.println("A的无参构造");
}
}
class B extends A{
public B(){
System.out.println("B的无参构造");
}
public B(String name){
/*
啥也没写.但别忘了,这里有个默认的super();
*/
System.out.println("B的有参构造");
}
}
class C extends B{
public C(){
this("linlin");
System.out.println("C的无参构造");
}
public C(String name){
this(name ,20);
System.out.println("C的有参构造(string)");
}
public C(String name,int age){
super(name);
System.out.println("C的有参构造(String,int)");
}
}
public class JavaStudy {
public static void main(String[] args){
new C();
}
}
输出结果
A的无参构造
B的有参构造
C的有参构造(String,int)
C的有参构造(string)
C的无参构造
// 理解啦吗, 反正我理解啦, 好耶 (☆▽☆)
虽然构造方法一连串调用父类的构造方法, 但实际的对象只有一个
代码理解4
class Employee
{
private String name;
private double salary;
private LocalDate hireDay;
public Employee(String n,double s,int year,int month,int day)
{
name = n;
salary = s;
hireDay = LocalDate.of(year,month,day);
}
}
class Manager extends Employee
{
double bonos;
public Manager(String name,double salary,int year,int month,int day)
{
super(name, salary, year, month, day);
//Manager类的构造器不能访问Employee的私有字段
// 必须用构造器来初始化这些字段
//使用super调用构造器的语句必须是子类构造器的第一条语句
bonos = 0;
}
}
代码理解5
public class E{
int x = 3;
String y = "ok";
}
public class M extends E{
public void printInfo(){
this.x = 10;
this.y = "Hello";
System.out.println("super x = "+super.x );
System.out.println("super y = "+super.y );
System.out.println("this x = "+this.x );
System.out.println("this y = "+this.y );
}
public static void main(String[] args){
new M.printInfo();
}
}
/*
super x = 10
super y = Hello
this x = 10
this y = Hello
*/
是 不 是 很 疑 惑 quq
为什么 super.x 和super.y 的输出不结果
是不是会想, 不是该调用父类的x和y吗 ?
为什么感觉是this.x 把父类的x也改了 !!!
最先开始我也很懵, 然后去网上搜也没有搜到具体相关的解释
然后看到了b站上动力节点的 Java教程 好像是P470和471 讲super内存图描述那两个视频
不懂的话可以去看看, 感觉看完大概都能理解了叭
这里大概总结一下:
-
super(实参) 的作用:
- 初始化当前对象的父类型特征
- 并不是创建新对象
-
super 关键字代表的是 当前对象的那部分父类型特征
-
虽然这部分父类型特征 是继承了父类型的
-
但是这些特征是属于子类的
-
-
还是去看看视频叭, 那个内存图很透彻hhhh
一切有关静态的东西
这玩意儿期末考试似乎好喜欢考静态的东西TAT
静态方法覆盖
- 静态方法无法覆盖( 即: 方法改写Override)
- 换句话说: 子类不能重写父类的静态方法
- 但可以在子类中重定义, 也就没有多态性了, 就没啥意义
public class Father{
public static void staticMethod(){
System.out.println("调用父类的静态方法");
}
}
public class Son extends Father{
public static void staticMethod(){
System.out.println("调用子类的静态方法");
}
}
public class Test{
public static void main(String[] args){
Father f = new Son();
f.staticMethod();
/**
*父类变量指向子类对象, 在调用一个被子类重定义的静态方法时
*首先 这是一个父类变量
*静态方法属于 类
*调用时,JVM会去父类的内存中找这个方法
*而不是调用子类的那个方法
*
*区别 文章开始写的那个静态绑定和动态绑定
*/
Son s = new Son();
s.staticMethod();
}
}
输出:
调用父类的静态方法
调用子类的静态方法
tring[] args){
Father f = new Son();
f.staticMethod();
/**
*父类变量指向子类对象, 在调用一个被子类重定义的静态方法时
*首先 这是一个父类变量
*静态方法属于 类
*调用时,JVM会去父类的内存中找这个方法
*而不是调用子类的那个方法
*
*区别 文章开始写的那个静态绑定和动态绑定
*/
Son s = new Son();
s.staticMethod();
}
}
输出:
```java
调用父类的静态方法
调用子类的静态方法