Java面向对象②

文章详细阐述了Java中的继承概念,包括子类如何调用父类私有成员、super关键字的使用、方法重写与重载的规则,以及继承的特点。同时,介绍了多态的定义、前提条件和成员访问特点,展示了多态在实际案例中的应用。此外,还涉及抽象类、抽象方法和接口的定义与使用,以及JDK8和JDK9接口的新特性。
摘要由CSDN通过智能技术生成

目录

一.继承  

1.定义

2.范例

①创建类的细节:

②子类如何调用父类中私有的成员

③优点

④使用情况

3.super关键字

①案例

 ②super 调用父类成员的省略规则

③this和super

4.方法重写和方法重载

①判断是否为方法重写

②方法重写的使用场景

③方法重写注意事项 

5.继承的特点

①继承中的成员访问特点——构造方法

②继承中构造方法执行流程——内存图解

6. 继承综合案例

6.final关键字

①特点

②final修饰成员变量的注意事项

③ final修饰变量的命名规范 

7.包

①建包的语法格式

②导  包

二.抽象类和抽象方法

1.抽象类的概念

2.抽象类的注意事项 :

3.抽象类和抽象方法的定义格式

 三.接  口

1.接口介绍

2.定义接口

3.接口的子类(实现类)

4.接口中的成员特点

①成员变量

②构造方法

③成员方法

5.类和接口之间的各种关系

①类和类的关系

②类和接口的关系

③接口和接口的关系

6.抽象类和接口的对比

①成员变量 

③构造方法

④功能

7.JDK8和JDK9接口的新特性

四.多  态

1.多态的介绍

2.多态的前提 :

①对象多态

②行为多态

3.多态的成员访问特点

4.多态的好处和弊端

5.多态的转型​编辑​编辑

6. 案例:模拟支付接口

五.代码块

1.局部代码块

2.构造代码块

3.静态代码块


一.继承  

1.定义

  •  让类和类之间产生关系(父子类关系),子类可以直接使用父类中非私有的成员,私有成员无法直接使用。
  • 父类中私有的成员,子类可以继承,但是不能直接访问

2.范例

  • public class Zi extends Fu{}
  •  Fu: 是父类,也被称为基类、超类 zi:是子类,也被称为派生类
class 父类{
    ...       //成员变量、成员方法
}
class 子类 extends 父类{
    ...       //类体
}

①创建类的细节:

1)一个Java文件可以编写多个class

2)保证类和类之间是平级关系

3)只能有一个被public修饰

4)当父类子类不在一个包下,应该书写导包代码

public class ExtendsDemo1 {
public static void main(String[] args) {
    Coder c = new Coder();
    c.name ="张三";
    c.age = 23;
    c.salary = 12000;
    }
}

class Employee {
String name;
int age;
double salary;
}

class Coder extends Employee {

}
class Manager extends Employee
{

}

②子类如何调用父类中私有的成员

调用set,get方法

public class extend {
    public static void main(String[] args)
    {
        Coder c = new Coder();
        c.setName("张三");
        c.setAge(23);
        c.setSalary(12000);
        System.out.println(c.getName() + "---" + c.getAge() + "---" + c.getSalary());
    }
}

class Employee {

    private String name;
    private int age;
    private double salary;

    public Employee() {
    }

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    
    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 double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

}

class Coder extends Employee{

}

class Manager extends  Employee{

}

③优点

提高代码的复用性

④使用情况

类与类之间,存在共性的内容,并且产生了is a 的关系,就可以考虑使用继承来优化代码

3.super关键字

①案例

public class Fu {
    int num = 10;
}
public class Zi extends Fu {
    int num = 20;
    public void method(){System.out.println(num);
}

public class Test {
    public static void main(String[] args) {
    Zi z = new Zi();
    z.method();//根据就近原则,此时打印出的是子类的20
    }

为了打印出父类中的成员,使用super关键字

public class ExtendsDemo2{
    public static void main(String[] args) {
    Zi z = new Zi();
    z.method();
    }
}

class Fu {
    int num = 10;
}

class Zi extends Fu {
    int num = 20;
    public void method(){
    System.out.println(num);//打印子类的变量10
    System.out.println(super.num);//打印父类的变量20
    }
}

 ②super 调用父类成员的省略规则


super.父类成员变量| super.父类成员方法()
被调用的变量和方法,在子类中不存在,super.可以直接省略的(建议不省略,明确是从父类还是从子类调用的成员)

class Coder extends Employee{
    public Coder(){

    }

    public Coder(String name, int age, double salary)){
        super(name,age,salary);//调用父类中的构造方法
    }

    @Override
        public void work(){
            System.out.println("姓名为:"+super.getName()+",年龄为:"
                    +super.getAge()+"工资为:"+super.getSalary()+"的程序员");
        }
}

③this和super

//开闭原则 : 对功能扩展做开放, 对修改代码做关闭 
public class test {
    public static void main(String[] args){
        A a1 = new A(1,2,3);
        A a2 = new A(1,2,3,4);


    }
}

class A{
    int a;
    int b;
    int c;
    int d;
    public  A()
    {

    }
    public  A(int a,int b,int c)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    public A(int a,int b,int c,int d)
    {
        this(a,b,c);//调用本类的方法,减少代码量
        this.d = d;
    }
}

4.方法重写和方法重载

①方法重载(overLoad) : 在同一个类中,方法名相同,参数不同,与返回值无关

参数不同: 类型不同,个数不同,顺序不同


②方法重写(override) : 在子父类当中,出现了方法声明一模一样的方法 (方法名,参数,返回值)

public static void main(String[] args) {
    Son s = new Son();
    s.method();//输出的是Son...method
}

class Father {
    public void method() {
    System.out.println("Father...method..");
    }
}

class Son extends Father {
    public void method() {
    System.out.println("Son...method");
    }
}

①判断是否为方法重写

在子类的方法前添加注解:@Override

如果没有报错,即为方法重写

②方法重写的使用场景

子类需要继承父辈的方法,但是需要在此基础上进行优化和增强

public class extend2 {
    public static void main(String[] args)
    {
        Son s = new Son();
        s.love();
    }
}

class Father{
    public void love()
    {
        System.out.println("送花");
        System.out.println("送肉");
    }
}

class Son extends Father{
    @Override//判断是否为方法重写
    public void love()
    {
        super.love();//保留父类的方法,在此基础上做改进,当不需要父类原有方法时,可以删除该条代码
        System.out.println("送口红");
        System.out.println("送衣服");//添加新的内容,改善父类方法
    }
}

输出结果:

送花
送肉
送口红
送衣服

③方法重写注意事项 

父类中私有方法不能被重写
子类重写父类方法时,访问权限必须大于等于父类 

5.继承的特点

Java只支持单继承,不支持多继承,但支持多层继承

package dome2;

public class extend3 {
    public static void main(String[] args) {
        C c = new C();//C中的对象可以同时调用A和B中的方法
        c.methodc();
        c.methodB();
        c.methodA();
    }

}


class A {
    public void methodA() {
        System.out.println("A...");
    }
}
//B为A的子类
class B extends A {
    public void methodB() {
        System.out.println("B...");
    }
}
//C为B的子类
class C extends B {
    public void methodc() {
        System.out.println("C...");
    }
}

①继承中的成员访问特点——构造方法

1.构造方法不能被子类继承,子类需要手动输入构造方法

        原因:构造方法名和类名要求一致

2.子类初始化之前,需要先对父类进行初始化

        原因:子类中可能要用到父类中的数据

        因此:子类需要访问父类的空参构造方法

public class extend2 {
    public static void main(String[] args) {
        Zi z1 = new Zi();
        Zi z2 = new Zi(10);
    }
}

class Fu {
    public Fu() {
        System.out.println("Fu类的空参构造方法");
    }
    public Fu(int num){
            System.out.println("Fu类的带参构造方法...");
        }

    }

class Zi extends Fu {
        public Zi() {
            System.out.println("Zi类的空参构造方法");
        }
        public Zi(int num){
                System.out.println("Zi类的带参构造方法...");
            }
}

输出结果:

Fu类的空参构造方法
Zi类的空参构造方法
Fu类的空参构造方法
Zi类的带参构造方法...

在所有构造方法的第一行代码,都默认隐藏了一句话 super();通过这句代码,访问父类的空参数构造方法 

细节: Java当中所有的类(处理object类),都直接或者间接的继承到了 object 类

②继承中构造方法执行流程——内存图解

6. 继承综合案例

 

public class extend {
    public static void main(String[] args)
    {
        Coder c = new Coder("张三",23,15000);
        c.work();
        
        
        Manager m = new Manager("李四",24,18000,5000);
        m.work();
        
    }
}
-----------------------------------------------------------------------------------------



class Employee {

    private String name;
    private int age;
    private double salary;
    
    public void work(){
        System.out.println("正在工作");
    }
    

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public Employee() {
    }
    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 double getSalary() {
        return salary;
    }


    public void setSalary(double salary) {
        this.salary = salary;
    }

}
-------------------------------------------------------------------

class Coder extends Employee{
//子类要单独创建空参和带参的构造方法
    public Coder(){
       
    }
    
    public Coder(String name, int age, double salary)){
        super(name,age,salary);
    }
    
    @Override
        public void work(){
            System.out.println("姓名为:"+super.getName()+",年龄为:"
                    +super.getAge()+"工资为:"+super.getSalary()+"的程序员");
        }
}
---------------------------------------------------------------------

class Manager extends  Employee {
//父类中没有的成员变量,子类要单独创建,并写出set,get方法
    private double bones;
    public Manager(){
    
    }

    public Manager(String name, int age, double salary)){
        super(name,age,salary);
    }
    
    public double getBones()
    {
        return bones;
    }
    public double setBones(double bones){
        this.bones = bones;
    }
    @Override
    public void work(){
        System.out.println("姓名为:"+super.getName()+",年龄为:"
                +super.getAge()+"工资为:"+super.getSalary()+"奖金为:"+bones+"的项目经理在分配任务");
    }
}

6.final关键字

final : 修饰符,可用于修饰方法,类,变量


①特点


        修饰方法: 表明该方法是最终方法,不能被重写

        修饰类: 表明该类是最终类,不能被继承

        注:当类中所有方法都是final修饰时,可直接用final修饰类

        修饰变量: 表明该变量是常量,不能再次被赋值
        基本数据类型:数据值不可改变

        引用数据类型:地址值不可改变,但是内容可以改变


②final修饰成员变量的注意事项


   1. final修饰成员变量,不允许修饰默认值

   2. final修饰成员变量的初始化时机
                1) 在定义的时候直接赋值
                2) 在构造方法中完成赋值 

③ final修饰变量的命名规范 

  • 如果变量名是一个单词,所有字母大写max MAX
  • 如果变量名是多个单词, 所有字母大写,中间使用下划线分割  maxValue  MAX_VALUE7.

7.包

包本质来说就是文件夹,用来管理类文件的


①建包的语法格式

package 公司域名倒写技术名称。报名建议全部英文小写,且具备意义
package com.itheima.domain;
public class Student {}
3.建包语句必须在第一行,一般IDEA工具会帮助创建

②导  包


相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!

导包格式:import 包名.类名;

假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。

package com.itheima.c;

import com.itheima.a.Student;

public class Test {
public static void main(String[] args) {
    Student stul = new Student();
    stu1.eat();
// 使用全类名创建对象 : 包名 + 类名
    com.itheima.b.Student stu2 = new com.itheima.b.Student();
    stu2.sleep();
    }
}

二.抽象类和抽象方法

1.抽象类的概念

抽象方法: 将共性的行为(方法)抽取到父类之后,发现该方法的实现逻辑无法在父类中给出具体明确,该方法就可以定义为抽象方法。
抽象类: 如果一个类中存在抽象方法,那么该类就必须声明为抽象类


abstract class Animal {
        public abstract void eat();//父类无法描述确切的行为,因此要构造抽象方法
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");//重写父类的方法
    }

}

class Dog extends Animal {
        @Override
        public void eat() {
            System.out.println("狗吃肉");//重写父类方法
        }
}

2.抽象类的注意事项 :

1. 抽象类不能实例化(不能创建对象)
        - 如果抽象类允许创建对象,就可以调用内部没有方法体的抽象方法了
2.抽象类存在构造方法

        - 交给子类,通过super进行访问
3.抽象类中可以存在普通方法
        - 可以让子类继承到继续使用
4.抽象类的子类
        1). 要么重写抽象类中的所有抽象方法

        2). 要么是抽象类

3.抽象类和抽象方法的定义格式

抽象方法的定义格式:

public abstract 返回值类型 方法名(参数列表)

示例:

public abstract void eat();
 

抽象类的定义格式:
public abstract class 类名{}

abstract class Animal{}

 三.接  口

1.接口介绍

接口:体现的思想是对规则的声明,Java中的接口更多体现的是对行为的抽象。接口中只有抽象方法。

2.定义接口

1.接口用关键字interface来定义

public interface 接口名 {}


2.接口不能实例化(不能创建对象)
3.接口和类之间是实现关系,通过implements关键字表示

public class 类名 implements 接口名 {}

3.接口的子类(实现类)


要么重写接口中的所有抽象方法
要么是抽象类(不建议)

public class interfaceTest {
    public static void main(String[] args) {
        InterImpl A1 = new InterImpl();//接口不能创建对象
        A1.method();
        A1.show();
    }
}

interface Inter{
    public abstract void show();//接口中全部是抽象方法
    public abstract void method();


}

class InterImpl implements Inter{
//子类必须重写方法
    @Override
    public void show() {
        System.out.println("show...");
    }

    @Override
    public void method() {
        System.out.println("method...");
    }
}

4.接口中的成员特点

①成员变量

        只能是常量;

        默认修饰符public,static,final,三者顺序没有要求


②构造方法


        没有


③成员方法


        只能是抽象方法
        默认修饰符: publrc abstract
        关于接口中的方法,JDK8 和 JDK9 中有一些新特性

5.类和接口之间的各种关系

①类和类的关系


        继承关系,只能单继承,但是可以多层继承


②类和接口的关系


        实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口


③接口和接口的关系


        继承关系,可以单继承,也可以多继承

public class interTest2 {

}

class Fu{
    public  void show(){
        System.out.println("show...");
    }
}
//接口中方法名可以一样,因为都没有具体描述,不会冲突
interface A{
    public void show();
}

interface B{
    public void show();
}

class son extends Fu implements A,B {
    //子类不需要重写接口中的方法,因为父类中存在同名方法,可以直接从父类中继承
}
    

6.抽象类和接口的对比

①成员变量 

抽象类 : 可以定义变量,也可以定义常量
接口:只能定义常量


②成员方法


抽象类 : 可以是定义具体方法,也可以定义抽象方法
接口:只能定义抽象方法


③构造方法


抽象类:有
接口:没有

④功能

抽象类:对事物做抽象(描述事物)

接口 :对行为抽象 (制定规则),使代码更规范

7.JDK8和JDK9接口的新特性

<一>JDK8版本接口特性:
1.允许定义非抽象方法,需要加入default关键字
        - 作用: 解决接口的升级问题
        - 注意事项:
                1.public可以省略,但是default不能省略
                2.默认方法,实现类是允许重写的,但是需要去掉default关键字


                3.如果实现了多个接口, 多个接口中存在相同的默认方法, 实现类必须重写默认方法
2.允许定义静态方法
        - 理解: 既然接口已经允许方法带有方法体了,干脆也放开静态方法,可以类名调用
        - 注意事项 :
                1.public可以省略,但是static不能省略
                2.接口中的静态方法, 只允许接口名进行调用,不允许实现类通过对象调用

public class interfaceTest {
    public static void main(String[] args) {
        AInterImpl a = new AInterImpl();
        a.method();

    }
}

interface A{
//加上default关键字,可以创建非抽象方法
    default void method(){
        System.out.println("A...method");
    }
    
}

interface Inter{
    public abstract void show();
    public abstract void print();
    default void method(){
        System.out.println("Inter...method");
    }



}

class AInterImpl implements Inter,A{

    @Override
    public void show() {
        System.out.println("AInterImpl...show...");
    }

    @Override
    public void print() {
        System.out.println("AInterImpl...print...");
    }

    @Override
    public void method() {
        Inter.super.method();//不能直接用super调用接口的方法,要加上接口名
        A.super.method();

    }
}

<二>JDK9版本接口特性:

        接口中允许定义私有方法

四.多  态

1.多态的介绍

同一个行为具有多个不同表现形式或形态的能力 

示例:

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入: 1.国内订单 2.国外订单");
        //创建一个接口型变量,存在两个不同的接受类
        OrderService orderService = null;
        int choice = sc.nextInt();
        switch (choice) {
            case 1:
                // 创建国内订单的业务类
                orderService = new OrderServicelmpl();
                break;
            case 2:
                // 创建国外订单的业务类
                orderService = new OrderoverseasServicelmpl();
                break;
        }
        //方法相同,但创建对象不同,运行结果不同
        orderService.create();
        orderService.findOne();
        orderService.findList();
        orderService.cancel();
        orderService.finish();
        orderService.paid();
    }
}

2.多态的前提 :

1)有继承 / 实现关系

2)有方法重写

3)有父类引用指向子类对象:

①对象多态


Animal a1 = new Dog();
Animal a2 = new Cat();

好处: 方法的形参定义为父类类型,这个方法就可以接收到该父类的任意子类对象了


②行为多态


好处:同一个方法,具有多种不同表现形式,或形态的能力

public class extend2 {
    public static void main(String[] args) {
        //Dog dog1 = new Dog();子类引用指向子类对象
        Animal a1 = new Dog();//父类引用指向子类对象
        Animal a2 = new Cat();

        useAnimal(new Dog());
        useAnimal(new Cat());
    }

    public static void useAnimal(Animal a) {
        a.eat();//传入不同对象,输出结果不同
    }
}

abstract class Animal {
        public abstract void eat();
    }

 class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

 class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

3.多态的成员访问特点

1. 成员变量 : 编译看左边(父类),运行看左边(父类)

 在编译的时候,会检查父类中有没有这个变量
        没有 : 编译出错
        有 : 编译通过,运行时使用父类中的变量值
2. 成员方法 : 编译看左边(父类),运行看右边(子类)
        在编译的时候,会检查父类中有没有这个方法
        没有 : 编译出错
        有 : 编译通过,但是运行的时候,一定会执行子类的方法逻辑
        原因: 担心你调用的方法,在父类中是一个抽象方法

示例:

public class interTest2 {
    public static void main(String[] args) {
        Fu F = new Zi();
        System.out.println(F.num);//输出父类成员10
       F.show();//执行子类方法
    }

}

class Fu{
    int num = 10;
    public void show(){
        System.out.println("Fu...show...");
    }
}

class Zi extends Fu{
    int num = 20;
    @Override
    public void show(){
        System.out.println("Zi...show...");
    }
}

3.多态创建对象,调用静态成员 :
   静态的成员,推荐类名进行调用
   细节:静态的成员,可以使用对象名调用,但这是一种假象
            生成字节码文件后,会自动将对象名调用,改成类名调用

4.多态的好处和弊端

多态的好处:提高了程序的扩展性

多态的弊端:不能使用子类的特有成员,父类中没有定义该成员时,编译无法通过

5.多态的转型

1.概述:如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException 

2.解决方法:

 关键字  instanceof
使用格式:
对象名 instanceof 类型
判断一个对象是否是一个类的实例通俗的理解:

判断关键字左边的对象,是否是右边的类型,返回boolean类型结果

6. 案例:模拟支付接口

 

interface Payment {
     void pay(double money);
 }
-----------------------------------------------------------------------------------------
public class test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请选择支付方式: 1,支付平台支付  2,银行卡网银支付 3,信用卡快捷支付");
        int choice = sc.nextInt();
        Payment payment = null;

        switch (choice) {
            case 1:
                payment = new PlatformPaymentimpl();
                break;
            case 2:
                payment = new BankcardPaymentImpl();
                break;
            case 3:
                payment = new CredicardPaymentImpl();
                break;
        }
            System.out.println("请输入您的支付金额:");
            double money = sc.nextDouble();
            payment.pay(money);

        }
    }
---------------------------------------------------------------------------------------
public class BankcardPaymentImpl implements Payment {
    @Override
    public void pay(double money) {
        System.out.println("通过银行卡网银支付了:"+money+"元");
    }
}
-----------------------------------------------------------------------------------------
public class CredicardPaymentImpl implements Payment{
    @Override
    public void pay(double money) {
        System.out.println("通过信用卡支付:"+money);
    }
}
-----------------------------------------------------------------------------------------
public class PlatformPaymentimpl implements Payment {
    @Override
    public void pay(double money) {
        System.out.println("通过支付平台支付了:"+money+"元");
    }
}

五.代码块

1.定义:
使用{}括起来的代码被称为代码块
2.分类

1.局部代码块

位置:方法中定义
作用:限定变量的生命周期,及早释放,提高内存利用率构造代码块

2.构造代码块

位置:类中方法外定义

特点:每次构造方法执行的时候,都会执行该代码块中的代码,并且在构造方法执行前执行

作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性

3.静态代码块

位置:类中方法外定义
特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次

作用:在类加载的时候做一些数据初始化的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值