java基础Day7 面向对象(2)

六、继承 Inheritance

6.1

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

extends:扩展。子类(派生类)是父类(基类)的扩展。

继承是类与类之间的关系。

java中只有单继承,没有多继承:一个儿子只能有一个爸爸,一个爸爸可以有多个儿子。

Inheritance>Application & Person & Student

package Inheritance;

public class Application {
    public static void main(String[] args) {

        Student student = new Student();
        student.say();

        System.out.println(student.money1);
        System.out.println(student.money2);
        //System.out.println(student.money3);//私有的,不属于子类
    }
}
package Inheritance;

//人
public class Person {

    //public
    public int money1 = 100_0000;

    //default
    int money2 = 200_0000;

    //protected

    //private
    private int money3 = 10_0000_0000;

    public void say(){
        System.out.println("说了一句话");
    }

}
package Inheritance;

//学生 是 人                派生类、子类
//子类继承了父类,就会拥有父类的全部方法(public)
public class Student extends Person {

}

ctrl+h,打开层次结构:

在java中,所有类都默认直接或间接继承Object类

6.2 super

Inheritance>Application & Person & Student

package Inheritance;

public class Application {
    public static void main(String[] args) {

        Student student = new Student();

        student.test1("name in test");
        student.test2();
    }
}
package Inheritance;

//人
public class Person {

    //protected
    protected String name = "name in Person";

    public void print(){
        System.out.println("Person");
    }

    //alt+insert-->构造函数-->无选择
    public Person() {
        System.out.println("Person无参执行了");
    }
}
package Inheritance;

public class Student extends Person {

    private String name = "name in Student";
    public void test1(String name){
        System.out.println(name);//name in test
        System.out.println(this.name);//name in Student
        System.out.println(super.name);//name in Person
    }

    public void print(){
        System.out.println("Student");
    }

    public void test2(){
        print();//Student
        this.print();//Student
        super.print();//Person
    }

    public Student() {
        //隐藏代码:调用了父类的无参构造
        //super();//且调用父类的构造器必须要在子类无参构造器的第一行
        //this("Hello");//如果调用子类自己的有参构造器,也必须要在子类无参构造器的第一行,且子类的有参构造器和父类构造器只能调用一个
        System.out.println("Student无参执行了");
    }
}

输出顺序是:

Person无参执行了
Student无参执行了
name in test
name in Student
name in Person
Student
Student
Person

Note:

  • super是调用父类的构造方法,必须在构造方法的第一个;
  • super必须只能出现在子类的方法或者构造方法中;
  • super和this不能同时调用构造方法;

vs. this:

  • 代表的对象不同:

​ this:本身调用着这个对象;

​ super:代表父类对象的引用。

  • 前提:

​ this:没有继承也可以使用;

​ super:只能在继承条件下才可以使用

  • 构造方法:

​ this():本类的构造;

​ super():父类的构造

6.3 方法重写 Override

Inheritance>Application & A & B

package Inheritance;

public class Application {
    public static void main(String[] args) {

        B b = new B();
        //b.test1();//输出Bteat()
        b.test2();//输出Bteat()

        //静态方法和非静态方法区别很大
        A a = new B();//父类的引用指向了子类;
        
        //静态方法:方法的类型只和最左边‘A’有关
        //a.test1();//输出Ateat()
        
        //非静态方法:子类重写了父类的方法
        a.test2();//输出Bteat()
    }
}
package Inheritance;

//重写都是方法的重写,和属性无关
public class A {

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

    public void test2() {
        System.out.println("Ateat()");
    }
}
package Inheritance;

public class B extends A {

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

    //alt+insert-->重写方法
    @Override//注解,有功能的注释
    public void test2() {
        System.out.println("Bteat()");
    }
}

这个标志为重写了

Note:

  • 需要有继承关系,子类重写父类的方法
  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大: public>protected>default>private
  • 抛出的异常:范围可以被缩小,但不能扩大:ClassNotFoundException-->Exception(大)

为什么需要重写?

  • 父类的功能子类不一定需要或满足;

Alt+insert-->override

七、多态 Polymorphism

7.1

动态编译

Polymorphism > Application & A & B

package Polymorphism;

public class Application {
    public static void main(String[] args) {

        //一个对象的实际类型是确定的
        //new Student;
        //new Person;

        //但可以指向的引用类型就不确定了
        //Student能调用的方法都是自己的或者继承父类的
        Student s1=new Student();
        //Person可以指向子类,但是不能调用子类独有的方法
        Person s2=new Student();//父类的引用指向子类
        //String s2=new Student();//不行,String和Student没有关系
        Object s3=new Student();

        s2.run();//当子类中没有重写run()时,输出run in Person;当子类重写run()后,输出run in Student
        s1.run();//当子类中没有重写run()时,输出run in Person;当子类重写run()后,输出run in Student

        s1.eat();
        //s2.eat();//不能调用子类的,对象能执行哪些方法主要看左边的类型,和右边关系不大
        ((Student)s2).eat();//强制转换,高转低
    }
}
package Polymorphism;

public class Person {

    public void run(){
        System.out.println("run in Person");
    }
}
package Polymorphism;

public class Student extends Person {
    @Override
    public void run() {
        System.out.println("run in Student");
    }

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

Note:

  • 多态是方法的多态,属性没有多态
  • 父类和子类,有联系,类型转换异常 ClassCastException
  • 存在的条件:继承关系;方法需要重写;父类引用指向子类对象:Father s1=new Son();

​ (static方法,属于类,它不属于实例;final 常量;private方法 都不能重写)

7.2 instanceof

instanceof 引用类型转换:判断一个对象是什么类型

Polymorphism > Application

System.out.println(X instanceof Y);//能不能编译通过
package Polymorphism;

public class Application {
    public static void main(String[] args) {

        Object s4=new Student();
        System.out.println(s4 instanceof Student);//输出true
        System.out.println(s4 instanceof Person);//输出true
        System.out.println(s4 instanceof Object);//输出true
        System.out.println(s4 instanceof Teacher);//输出false
        System.out.println(s4 instanceof String);//输出false
        System.out.println("=================");

        Person s5=new Student();
        System.out.println(s5 instanceof Student);//输出true
        System.out.println(s5 instanceof Person);//输出true
        System.out.println(s5 instanceof Object);//输出true
        System.out.println(s5 instanceof Teacher);//输出false
        //System.out.println(s5 instanceof String);//编译报错
        System.out.println("=================");

        Student s6=new Student();
        System.out.println(s6 instanceof Student);//输出true
        System.out.println(s6 instanceof Person);//输出true
        System.out.println(s6 instanceof Object);//输出true
        //System.out.println(s6 instanceof Teacher);//编译报错
    }
}

类型转换:

package Polymorphism;

public class Application {
    public static void main(String[] args) {
     
        //类型之间的转换:父-->子 高-->低
        //高             低
        Person s7=new Student();
        //student.eat();//报红
        //将这个对象转换为Student类型,我们就可以使用Student类型的方法
        ((Student)s7).eat();

        Student s8=new Student();
        Person person = s8;//低转高可以直接转,不过子类转换为父类可能丢失一些方法
    }
}
  • 父类引用指向子类的对象
  • 把子类转换为父类:向上转型,不用强制转换
  • 把父类转换为子类:向下转型,强制转换
  • 方便方法的调用,减少重复的代码

八、static关键字详解

StaticSummary > Student

package StaticSummary;

//static
public class Student {

    private static int age;//静态变量
    private double score;//非静态变量

    public void run(){

    }

    public static void go(){

    }

    public static void main(String[] args) {
        Student s1 = new Student();

        System.out.println(Student.age);
        //System.out.println(Student.score);//报红
        System.out.println(s1.age);
        System.out.println(s1.score);

        new Student().run();
        Student.go();
        go();
        //run();//报红,和类一起加载
    }
}
package StaticSummary;

public class Person {

    {
        //匿名代码块
        System.out.println("匿名代码块");
    }

    static{
        //静态代码块
        System.out.println("静态代码块");
    }

    public Person() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        /*
        输出顺序:静态代码块
                匿名代码块
                构造方法
         */
        System.out.println("====================");

        Person person2 = new Person();
        /*
        输出:匿名代码块
            构造方法
        static{}没了,它只执行一次
        static{}一般用来赋初始值,因为它和对象是同时产生的
         */
    }
}

静态导入包:

package StaticSummary;

import static java.lang.Math.random;//静态导入包
import static java.lang.Math.PI;

public class Test {
    public static void main(String[] args) {
        //System.out.println(Math.random());//输出一个随机数
        System.out.println(random());
        System.out.println(PI);
    }
}

被final修饰的类不能被继承

九、抽象类

AbstractClass > A & Action

package AbstractClass;

//abstract 抽象类: 类 extends:  单继承         (接口可以多继承)
public abstract class Action {

    //约束 有人帮我们实现
    //abstract抽象方法,只有方法名字,没有方法的实现
    public abstract void doSometing();

    // 1. 不能new这个抽象类,只能靠子类去实现它;约束

    // 2. 抽象类中可以写普通方法
    // 3. 抽象方法必须要在抽象类中
    public void hello(){

    }

    // 抽象的抽象:约束
    //new 存在构造器吗?
    //存在的意义:抽象出来,提高开发效率
}
package AbstractClass;

//抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非子类也是抽象类
public class A extends Action{
    @Override
    public void doSometing() {
    }
}

十、接口

普通类:只有具体的实现;

抽象类:具体的实现和规范(抽象方法)都有;

接口:只有规范,自己无法写方法,专业的约束;约束和实现分离;面向接口编程

接口定义的是一组规则

接口的本质是契约

声明接口的关键字是interface

package Interface;

//interfacce 定义的关键字,接口都需要有实现类
public interface UserService {
    //属性默认是常量 public static final
    int AGE = 99;

    //接口中的所有定义其实都是抽象的public abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}
package Interface;

public interface TimeService {
    void timer();
}
package Interface;

//一个类可以实现接口
//实现了接口的类,就需要重写接口中的方法
public class UserServiceImpl implements UserService, TimeService {//多继承,利用接口实现多继承
    //alt+insert-->实现方法
    @Override
    public void timer() {

    }

    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }
}

Note:

  • 约束
  • 定义一些方法,让不同的人实现
  • 接口不能被实例化,接口中没有构造方法
  • implements可以实现多个接口
  • 实现了接口的类必须要实现接口中的方法

十一、内部类(奇葩代码)

package InnerClasses;

public class Application {
    public static void main(String[] args) {

        Outer outer = new Outer();
        //通过外部类来实例化内部类
        Outer.Inner1 inner = outer.new Inner1();
        inner.in();
        inner.getID();
    }
}
package InnerClasses;

public class Outer {

    private int id = 10;
    public void out(){
        System.out.println("这是外部的方法");
    }

    public class Inner1{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //获得外部类的私有属性
        public void getID(){
            System.out.println(id);
        }
    }

    public static class Inner2{
    }

    public void method(){
        //局部内部类
        class Inner3{
            public void in(){

            }
        }
    }
}

//一个java类中可以有多个class类,但是只能有一个public class
class A{
    public static void main(String[] args) {

    }
}
package InnerClasses;

public class Test {
    public static void main(String[] args) {
        Apple apple1 = new Apple();
        //没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();

        UerService uniservice=new UerService(){
            @Override
            public void hello() {

            }
        };
    }
}

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

interface UerService{

    void hello();
}
posted @ 2025-01-26 20:54  tse121  阅读(8)  评论(0)    收藏  举报