🌎向上转型的概念:父类调用子类对象
class Animal{
public String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
}
class cat extends Animal{
public String color;
public cat(String name,int age)
{
super(name,age);
}
public void eat()
{
System.out.println("吃");
}
}
public class Review {
public static void main(String[] args) {
//父类调用子类对象
Animal animal1=new cat("mimi",18);
System.out.println(animal1.age);
}
}

三种时机:1.直接赋值
2.传参
3.返回值
public class Review {
//父类接受
public static void func(Animal animal1)
{
System.out.println(animal1.age);
}
public static Animal func1(){
return new cat("david",16);
}
public static void main(String[] args) {
//父类调用子类对象
//1.直接赋值
Animal animal1=new cat("mimi",18);
//传参
cat cat1=new cat("er",19);
func(cat1);
//返回值
Animal animal=func1();
}
}
🔥🔥上面的代码只有子类有eat方法,但是如果父类也有eat方法,则两个eat方法构成了重写。上面的图中提到向上转型是父类调用子类对象,但是父类只能调用父类本身被子类继承过去的成员(也就是父类本身自己的成员),那么按照推断。Animal animal=new cat(“mimi”,18);
animal1.eat()应该调用自己本身的eat.打印“父类吃”。但结果却出人意料。请看下方截图
class Animal{
public String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat()
{
System.out.println("父类吃");
}
}
class cat extends Animal{
public String color;
public cat(String name,int age)
{
super(name,age);
}
//重写父类方法
public void eat()
{
System.out.println("吃");
}
}
public class Review {
public static void main(String[] args) {
Animal animal1=new cat("mimi",18);
animal1.eat();
}

总结:(1)发生运行时绑定的条件1.子类.父类具有同名的覆盖方法(重写)
2.发生了向上转型
(2)反编译角度在代码进行编译时确实是调用的父类自身的方法,但是在运行时却是实现的是子类的同名方法,这种现象叫做运行时绑定
在子类中写一个和父类完全一样的方法就叫做重写
class Animal{
public String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat()
{
System.out.println("父类吃");
}
}
class cat extends Animal{
public String color;
public cat(String name,int age)
{
super(name,age);
}
//重写
public void eat()
{
System.out.println("吃");
}
}
🌎1.需要重写的方法不能是被final修饰的,被final修饰的方法是密封的不能被修改
2.被重写的方法,访问修饰限定符一定不能是private.(因为重写中子类的方法的访问权限不能低于父类的方法访问权限)
3.被重写的方法,子类中的访问修饰限定要大于等于父类中的访问修饰限定
4. 普通方法可以重写, static 修饰的静态方法不能重写.
5.重写的方法返回值类型不一定和父类的方法相同(但是建议最好写成相同, 特殊情况除外).

//错误实例:
public class Animal {
public void eat(String food) {
...
}
}
// Bird.java
public class Bird extends Animal {
// 将子类的 eat 改成 private
private void eat(String food) {
...
}

1.基本理解:同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
2.代码层面理解:什么时候发生多态:
1.父类引用 引用子类对象
2.父类和子类有同名的覆盖方法
3.通过父类引用这个这个重写的方法
class Shape{
public void draw()
{
System.out.println("画一个图形");
}
}
class Circle extends Shape{
public void draw(){
System.out.println("画一个圆");
}
}
class React extends Shape{
public void draw() {
System.out.println("画一个方形");
}
}
public class Review {
//向上转型的第二中的形式:传参
public static void drawMap(Shape shape)
{
shape.draw();
}
public static void main(String[] args) {
//不同表现形式
Shape shape1=new Circle();
Shape shape2=new React();
drawMap(shape1);
drawMap(shape2);
}
}

1.含义:如果一个方法被abstract修饰则这个方法是抽象方法(抽象方法可以没有具体的实现)
2.包含抽象方法的类叫做抽象类(抽象方法必须放在抽象类中)
3.抽象类的主要作用就是用来继承的
要点及注意事项如下:
package bite;
//抽象类一定不能被final修饰,因为final修饰的类是密封的,里面的方法不能被重写
abstract class Shape{
//当某个方法没有被实例化的必要。可以将他进行抽象化
//抽象化的方法必须放在抽象类中
//和其他类一样也可以添加成员变量,和普通类区分的唯一区别是类中有抽象方法
//public String color;
int a=10;
public abstract void draw();//并没有被具体应用
}
class circle extends Shape{
//继承抽象类。必须先重写抽象类中的抽象方法
//(除非子类也是抽象类,则第一次继承不用重写,第二次继承必须重写)
@Override
public void draw() {
System.out.println("画一个⚪");
}
}
class React extends Shape{
@Override
public void draw() {
System.out.println("画一个正方形");
}
}
class triangle extends Shape{
@Override
public void draw() {
}
}
public class abstractFunc {
//多态
public static void drawMap(Shape shape)
{
shape.draw();
}
public static void main(String[] args) {
//抽象类仍然可以发生向上转型
//抽象类能不能被实例化,不能写成 Shape shape1=new Shape()
Shape shape1=new circle();//不能实例化但可以向上转型
drawMap(shape1);
Shape shape2=new React();
drawMap(shape2);
}
}
1.接口中的方法默认为,public abstract(接口中的方法必须是抽象方法)
2.抽象方法不能被实例话,只能在子类继承中重写实现功能
3.JDK1.8可以具体实现只需加上default
4.接口中的变量默认为常量(public static final),必须赋初始值
5.和抽象类一样,接口不能被实例化,但可以发生向上转型
6.接口与类的关系(implentments(实现关系))
7.接口的目的:解决java单根继承的问题(一个类虽然只能继承一个类,但却可以实现多个接口)
8.类实现接口必须重写接口中方法(接口中方法都默认是抽象方法)
8.只要类实现了接口,就可以利用接口向上转型,实现类的动作。
package interfaceBite;
//Shape 并没有包含别的非抽象方法, 也可以设计成一个接口
//接口只有在继承后再能被间接使用
interface Shape{
//接口中的方法默认为,public abstract(接口中的方法必须是抽象方法)
//抽象方法不能被实例话,只能在子类继承中重写实现功能
//JDK1.8可以具体实现只需加上default
//接口中的变量默认为常量(public static final)
void draw();
public static final int a=10;
/* default void color()
{
System.out.println("color");
}
*/
}
//类实现接口必须重写当中的方法
class Circle implements Shape{
@Override
public void draw() {
System.out.println("画一个⚪");
}
}
class React implements Shape{
public void draw()
{
System.out.println("画一个正方形");
}
}
public class interFace {
public static void drawMap(Shape shape)
{
shape.draw();
}
public static void main(String[] args) {
//Shape是接口不能出现Shape shape1=new Shape();这样的形式,因为它不能被实例化
Shape shape1=new Circle();
Shape shape2=new React();
drawMap(shape1);
drawMap(shape2);
}
}
接口一般是一个动作,类是一个发出动作的个体。类通过实现接口达到实现这个动作的目的
package interfaceBite;
//一个类
class Animal{
public String name;
public Animal(String name)
{
this.name=name;
}
}
//多个接口
interface IFlying{
void fly();
}
interface IRunning{
void run();
}
interface ISwing{
void swim();
}
//疑惑:我直接在子类中写一个run方法不行吗为什么用接口
//答:比较方便:接口实现了以动作为主体,不管对象,
// 只管是否可以完成这个动作
class Cat extends Animal implements IRunning{
public Cat(String name)
{
super(name);
}
public void run()
{
System.out.println("猫会跑");
}
}
class Fish extends Animal implements ISwing{
public Fish(String name) {
super(name);
}
@Override
public void swim() {
System.out.println("乌龟会游");
}
}
//extends和implements前后顺序不要变
class Frog extends Animal implements IRunning,ISwing{
public Frog(String name) {
super(name);
}
@Override
public void run() {
System.out.println("青蛙会跑");
}
@Override
public void swim() {
System.out.println("青蛙会游");
}
}
//上面的代码展示了 Java 面向对象编程中最常见的用法:
// 一个类继承一个父类, 同时实现多种接口
//不关心对象只关心谁可以完成这个动作
public class understandInterface {
public static void walk(IRunning running)
{
running.run();
}
//接口中方法的实例化不能由父类对象调用,必须由借口自己调用
// (接口中的都为抽象方法)
public static void main(String[] args) {
IRunning running=new Cat("咪咪");
IRunning running1=new Frog("青青");
walk(running);
walk(running1);
}
}
compare是java中自带的一种接口,里面有comareTo方法,我们通过改写compareTo方法决定判定标准。可能这么说还不够具体,请看下面的代码:
import java.util.Arrays;
class student implements Comparable<student>{
String name;
int age;
int score;
public student(String name,int age,int score)
{
this.name=name;
this.age=age;
this.score=score;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
//一定要是可以比较的标准
@Override
public int compareTo(student o) {
if (this.score>o.score)
{
return 1;
}
else if (this.score==o.score)
{
return 0;
}
else {
return -1;
}
}
}
public class compares {
public static void main(String[] args) {
student stu1 = new student("里斯", 18, 90);
student stu2 = new student("david", 19, 60);
//if(stu1>stu2)此时不能比较,有多重标准。要用到compare
//stu1调用compareTo所以他是主体,stu2 是o;
if (stu1.compareTo(stu2) > 0) {
System.out.println("student1的分数高");
}
student [] str={stu1,stu2};
Arrays.sort(str);
System.out.println(Arrays.toString(str));
}
}
⛳如果直接比较if(stu1<stu2)是错误的,因为一个学生有姓名,年龄,分数。没有判定标准,我们需要重写compare中的方法,决定判定标准。
看到如上代码要注意对应关系:stu1.compareTo(stu2),其中stu1,对应compareTo方法的this.score,stu2对应o.score.注意主客体关系
