跟着大佬学java第八课,面向对象编程(三)

面向对象编程

多态

什么是多态

  1. 动态编译:类型:可扩展性
  2. 即同一方法可以根据发送对象的不同而采用多种不同的行为方式
  3. 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
  4. 多态存在的条件
    1. 有继承关系
    2. 子类重写父类方法
    3. 父类引用指向子类对象
  5. 多态是方法的多态,属性没有多态性
  6. instanceof 和 类型转换

多态样例

//父类
public class Person {
    public void run(){
        System.out.println("father");
    }

    public void fatherSay(){
        System.out.println("father told son to study");
    }
}
//子类
public class Student extends Person {
    @Override
    public void run() {
        System.out.println("son");
    }

    public void eat(){
        System.out.println("son is eating");
    }
}
//主方法调用
public class Application {
    public static void main(String[] args) {

        //指向的引用类型不确定,可以是指向实际类型,可以是父类指向子类,可以是Obejct指向实际类型
        //对象的实际类型是确定的(new Student();)
        Student s1 = new Student();     //子类指向引用子类
        Person s2 = new Student();      //父类指向引用子类,子类不能指向父类
        Object s3 = new Student();

        //单独运行父类方法,结果:father
//        s2.run();

        //运行父类方法后,运行子类中的方法,子类将父类的方法重写了,结果:son son
//        s2.run();
//        s1.run();

        //子类可正常调用子类中的方法,结果:son is eating
//        s1.eat();

        //父类无法直接调用子类中的方法,报错
//        s2.eat();

        //子类可以继承并调用哦父类的方法,结果:father told son to study
//        s1.fatherSay();
    }
}

instanceof关键字

作用

  1. instanceof 是 Java 的一个二元操作,符等 ==,>,< 操作符。
  2. instanceof 是 Java 的保留关键字。它的作用是测试它映射的对象是否是它正确的类的实例,返回布尔值的数据类型。

判断Object类与子类、其他类的关系

//多态的类型判断,通过instanceof判断测试它映射的对象是否是它正确的类的实例
public class Application {
    public static void main(String[] args) {
        Object object = new Student();
        
        //通过instanceof关键字判断类型是否相同
        //Object>Person>Student ----父类子类继承关系,object指向了Student,所以类型相同
        //Object>Person>Teacher ----Teacher有继承关系,但父类没有指向Teacher,所以类型不同
        //Object>String ----不在同一个包下,没有任何关系,多以类型不同
        System.out.println(object instanceof Student);  	//true
        System.out.println(object instanceof Person);  		//true
        System.out.println(object instanceof Object);  		//true
        System.out.println(object instanceof Teacher); 		//false
        System.out.println(object instanceof String); 		//false
    }
}

判断Person类与子类、父类、其他类的关系

//多态的类型判断,通过instanceof判断测试它映射的对象是否是它正确的类的实例
public class Application {
    public static void main(String[] args) {
         Person person = new Student();
        
        //通过instanceof关键字判断类型是否相同
        //Object>Person>Student ----父类子类继承关系,object指向了Student,所以类型相同
        //Object>Person>Teacher ----Teacher有继承关系,但父类没有指向Teacher,所以类型不同
        //Object>String ----不在同一个包下,没有任何关系,多以类型不同
       
        System.out.println(person instanceof Student);  //true
        System.out.println(person instanceof Person);  //true
        System.out.println(person instanceof Object);  //true
        System.out.println(person instanceof Teacher); //false
//        System.out.println(person instanceof String); //编译就报错,Person和String都是属于Object底下的类,没有父子关系,无法进行比较
    }
}

判断Student类与子类、父类、其他类的关系

//多态的类型判断,通过instanceof判断测试它映射的对象是否是它正确的类的实例
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        
        //通过instanceof关键字判断类型是否相同
        //Object>Person>Student ----父类子类继承关系,object指向了Student,所以类型相同
        //Object>Person>Teacher ----Teacher有继承关系,但父类没有指向Teacher,所以类型不同
        //Object>String ----不在同一个包下,没有任何关系,多以类型不同
       
        System.out.println(student instanceof Student);  //true
        System.out.println(student instanceof Person);  //true
        System.out.println(student instanceof Object);  //true
//        System.out.println(student instanceof Teacher); //编译就报错,Student属于Object下Person下的类,Teacher属于Object下Person下的类,没有父子关系,无法进行比较
//        System.out.println(person instanceof String); //编译就报错,Student属于Object下Person下的类,String属于Object下的类,没有父子关系,无法进行比较
    }
}

instanceof 小结

  1. 父类中有,子类中没有,父类实体类使用时调用自身的方法
  2. 父类中有,子类中没有,子类会继承父类中的方法
  3. 父类中有,子类中也有,父类实体类使用时调用自身的方法
  4. 父类中有,子类中也有,子类实体类使用时会按照子类中的方法*重写父类的方法
  5. 父类中没有,子类中有,父类无法调用子类中的方法,子类可调用自身的方法

注意事项

  1. 多态是方法的多态,属性么有多态
  2. 父类和子类,类型相同,否则类型转换异常(ClassCastException)
  3. 多态存在条件:继承关系,方法需要重写,父类的引用指向子类对象
  4. 无法使用多态的情况
    1. static 方法,属于类,不属于实例,无法重写
    2. final 常量,无法重写
    3. private 私有方法,无法重写

类型转换

代码样例

//子类
public class Student extends Person {
    public void go(){
        System.out.println("go");
    }
}
//父类
public class Person {
    public void run(){
        System.out.println("father");
    }
}
//方法体
public class Application {
    public static void main(String[] args) {

        //对应的类型
        Student s1 = new Student();
        Person p1 = new Person();

        //类之间强制转化:父   子
        //子类型转化为父类型,父类型指向子类型
        //高类型  <----  低类型
        Person obj = new Student();        //1.默认转换
        Person p2 = s1;         //1.默认转换
//        p2.go();      //子类转换为父类,可能会丢失子类中的方法

        //obj.go();     //编译报错,父类无法调用子类中的方法
        //父类型转化为子类型,子类型指向父类型需要强制转化
        //可以通过将父类强制转化为子类,然后调用子类中的方法
        //低类型   <----   高类型
        Student student = (Student) obj;
        student.go();       //go

    }
}

类型转换 小结

  1. 父类引用指向子类的对象
  2. 把子类转换为父类,向上转型
  3. 把父类转换为子类,乡下转型,强制转换
  4. 方便方法的调用,减少重复的代码

抽象三大特性:封装、继承、多态!

static关键字

static关键字定义的属性和方法为静态的,可以在方法里直接调用

非静态属性和方法,需要通过new关键字来调用

public class Student {

    private static int age; //静态的变量     多线程使用
    private double score;//非静态的变量

    public void run(){
        go();       //非静态方法可以调用静态方法
    }

    public static void went(){

    }
    public static void go(){
        //静态方法里可以调用静态方法,无法调用动态方法,可以调用goto(),无法调用run()
        //类加载时已加载静态方法,类加载后加载非静态方法
    }

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

        System.out.println(Student.age);    //静态变量可以直接调用
//        System.out.println(Student.score);  //无法从静态上下文中引用非静态 变量 score
        System.out.println(sl.age);
        System.out.println(sl.score);

        new Student().run();        //通过new调用里面的run()方法,无法直接调用类里的非静态方法
        Student.go();           //直接调用当前类中的go()方法
    }
}

代码块的运行在构造器之前,静态代码块只有第一次加载的时候生成,非静态代码块每次类加载的时候都会重新加载

public class Person {
    //执行顺序2:赋值初始值
    {
        //代码块(匿名代码块)
        System.out.println("匿名代码块");
    }

    //执行顺序1:只执行一次
    static {
        //静态代码块
        System.out.println("静态代码块");
    }

    //执行顺序3
    public Person(){
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        //第一次执行
        Person person1 = new Person();
        System.out.println("====================================");
        //第二次执行
        Person person2 = new Person();
    }
}

结果:
静态代码块
匿名代码块
构造方法
====================================
匿名代码块
构造方法

静态包导入

//静态导入包,导入后可直接通过方法名调用对应的方法
//import java.lang.Math.random;  //报错,无法直接导入包内方法,需要使用static关键字
import static java.lang.Math.random;

public class Test {
    public static void main(String[] args) {
        //不导入包,直接调用随机数方法
        System.out.println(Math.random());
        //静态导入包后直接调用随机数方法
        System.out.println(random()); 
    }

    //Math中存在final关键字,被final定义的方法无法继承,没有子类
    //People继承Person类
    public final class People extends Person{
    }
    //因People类使用了关键字final,所以其他类无法继承
//    public class one extends People{
//    }
}

抽象类

抽象类特点:

  1. 单继承
  2. 可以有普通方法和抽象方法
  3. 通过子类去实现功能
//abstract 抽象类
//类继承 extends 单继承,java内的类没有多继承。但是接口可以多继承
public abstract class Action {

    //约束
    //abstract,抽象方法,只有方法名字,没有方法的实现!
    public abstract void doSomeThing();

    //1. 不能new这个抽象类,只能靠子类去实现它:约束    //无法 new Action();
    //2. 抽象类中可以有抽象方法,也可以有非抽象方法;非抽象类中不能有抽象方法(抽象方法必须存在抽象类中)

    public void hello(){
        System.out.println("非抽象方法hello();");
    }

    //抽象类不能 new ,但是内部存在构造器
    //抽象类存在的意义,节省代码空间,提高开发效率
}

接口

接口和抽象类的区别

普通类:只有具体实现

抽象类:具体实现和规范(抽象方法)都有(使用abstract定义类)

接口:只有规范,自己无法些方法,约束和实现分离:面向接口编程(通过interface定义接口类,通过implements继承接口定义实现类)

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是……则必须能……”的思想

接口的本质是契约,制定好以后都要遵守

OO(面向对象)的精髓,是对对象的抽象,最能体现这一点的就是接口。

为什么我们讨论设计,模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

声明类的关键字是class,声明接口的关键字是interface

接口实例

定义接口UserService

//锻炼抽象的思维
//接口定义关键字 interface
public interface UserService {
    //接口里不能写方法
//    public void run(){
//    }

    //常量,接口里不建议使用
    int age = 99;       //public static final int age = 99;

    //接口中的所有定义的方法其实都是抽象的 public abstract,可以不写
    //返回类型 方法名(参数)
    void add(String name);
    void del(String name);
    void update(String name);
    void query(String name);
}

定义接口Timer

public interface TimeService {
    void timer();
}

通过类实现接口中的方法

// 类 可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口中的方法
// 多继承 (implements UserService,TimeService 继承了两个接口)
public class UserServiceImpl implements UserService,TimeService {
    //需要重写,全部继承的所有接口类中的方法,否则报错
    @Override
    public void add(String name) {  //方法体  }
        
    @Override
    public void del(String name) {  //方法体  }

    @Override
    public void update(String name) {  //方法体  }

    @Override
    public void query(String name) {  //方法体  }

    @Override
    public void timer() {  //方法体  }
}

接口的作用

  1. 约束,没有具体的实现
  2. 定义一些方法,让不同的人实现,可以通过接口调用方法,不同的实现
  3. 方法 public abstract,抽象的
  4. 常量 public static final,接口中不建议使用
  5. 接口不能被实例化,接口中没有构造方法
  6. implements可以实现多个接口
  7. 必须要重写接口中的方法

内部类(扩展部分)

内部类就是在一个类的内部再定义一个类(扩展部分,了解即可)

  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类
  5. lambada表达式

内部类实例1

//外部类
public class Outer {

    private int id = 10;

    public void out(){
        System.out.println("这是外部类的方法");
    }

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

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

    //静态内部类
    public static class Inner2{
        public void in(){
            System.out.println("这是静态内部类的方法");
        }

        //获得外部类的私有属性
        public void getId(){
//            System.out.println(id);       //id不是静态属性,static方法里无法获取,静态类无法访问非静态属性和方法
        }
    }

    public void method(){
        //局部内部类可以在方法里
        class Inner3{
        }
    }
}

//一个java类中能有一个 public class,但是可以有多个class
class A{
    //可以main方法等
}

内部类实例2

public class Test {
    public static void main(String[] args) {
        //匿名内部类,直接 new,不赋值,不用将实例保存早变量中
        new Apple().eat();
    }

    //调用自身的内部接口类
    UserService userService = new UserService(){
        @Override
        public void hello() {}
    };
}

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

//接口
interface UserService{
    void hello();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值