面向对象编程

本文详细介绍了Java中的封装、继承和多态概念。封装通过private关键字实现字段和方法的保护;继承使用extends关键字,一个子类只能继承一个父类,子类会继承父类的非private字段和方法;多态包括向上转型、向下转型和运行时绑定,展示了Java的灵活性。同时,文章还讲解了抽象类和接口的使用,以及Comparable和Comparator接口在排序中的应用。
摘要由CSDN通过智能技术生成

封装

1.语法

使用private关键字,修饰字段和方法,只能在当前类中使用

意义:安全性,可复用性

继承

1.语法

class 子类 extends 父类{}
意义:提高代码复用性
  1. 在java中,只能通过extends来继承一个类

  2. java中一个子类只能继承一个父类

  3. 子类会继承父类的所有的字段和方法

  4. 对于父类的private方法,子类是无法访问的

  5. 子类和父类有同名的属性,会优先调用子类中的属性。

    class Animal{
        public String name="haahah";
        public int age;
    }
    class Dog extends Animal{
        public String name="wangwang";//如果没有这一行,则输出结果为haahah
        public Dog(){
            System.out.println(name);
        }
    }
    
    public class TestExtends {
        public static void main(String[] args) {
        Dog d=new Dog();
        }
    }
    //输出结果:wangwang
    
  6. 引入super:父类对象的引用(必须写在子类构造方法的第一行)

    1. super.data //访问父类的成员变量
    2. super.func() //访问父类的成员方法
    3. super() //访问父类的成员的构造方法
  7. 子类继承父类之后,要想实例化子类对象,一定要先帮父类进行构造。所有构造对象,只能通过构造方法进行构造

    1. 所有类编译器会提供一个空参构造器,若自主的写入一个带参的构造方法,编译器不会再提供空参构造器
    class Animal{
        public String name="hahahah";
        public int age;
      //提供了带参构造器
        public Animal(String name,int age){
            this.name=name;
            this.age=age;
        }
        public void test(){
            System.out.println(name+"今年"+age+"岁了");
        }
    }
    class Dog extends Animal{
        public String name;
      //子类也要提供带参构造器
        public Dog(String name,int age){
            super(name,age);//必须写在第一行
        }
    
    }
    
  8. 注:继承最好不要超过3层,可以使用final修饰类,该类不能被继承了

    class A{
        public int age=10;
    }
    
    class B extends A{
        public int age=20;
    }
    //final修饰类,成密封类
    final class C extends B{
        public void func(){
            System.out.println(super.age);//这里的super只指直接父类B
        }
    }
    

多态

1.1向上转型

 Animal animal=new Dog("xiugou",10);

向上转型之后,只能通过父类引用访问父类的属性和方法,不能访问子类特有的属性和方法:swimming()是Dog子类特有的方法

 class Animal{
    public String name;
    public int age;
    public Animal(String name,int age){
        this.name=name;
        this.age=age;
    }
}
class Dog extends Animal{
    public String name;
    public Dog(String name,int age){
        super(name,age);
    } 
    public void swimming(){
        System.out.println(name+"游泳~");
    }
}
 
 public static void main(String[] args) {
    Animal animal=new Dog("xiugou",10);
    //animal.swimming();//编译错误
    }

向上转型发生时机:

①直接赋值 Animal animal=new Dog("xiugou",10);

②传参

class Animal{
    public void message(){
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    public void message() {
        System.out.println("Dog");
    }
}
class Bird extends Animal{
    public void message() {
        System.out.println("Bird");
    }
}
public class TestExtends {
    public static void func(Animal animal){
        animal.message();
    }

    public static void main(String[] args) {
        Dog dog=new Dog();
        func(dog);
        Bird bird=new Bird();
        func(bird);
    }
}
//运行结果:Dog
//        Bird

通过这种引用,调用同一种方法,表现出不同形式,这种思想叫做多态。

③返回值

public static Animal func2(){
  Dog dog=new Dog();
  retun dog;
}

1.2 向下转型

上述代码可以改为:

 
 public static void main(String[] args) {
    Animal animal=new Dog("xiugou",10);
    //animal.swimming();//编译错误
   ((Dog) animal).swimming();//正确,向下转型
    }

但是,向下转型不安全

1.3 运行时绑定

这个过程叫做运行时绑定:

class Animal{
    public String name="hahahah";
    public int age;
  
    public void message(){
        System.out.println("Animal");
    }
}
class Dog extends Animal{
    @Override
    public void message() {
        System.out.println("Dog");
    }
}
public class TestExtends {
    public static void main(String[] args) {
    Animal animal=new Dog();
    animal.message();
    }
}
//运行结果:Dog

A.对比子类和父类的message() 方法,我们发现:

  1. 函数名称相同
  2. 函数的参数列表相同(个数,类型)
  3. 函数返回值相同(也可不相同,但返回值之间要构成父子类关系,用的少)

我们将满足这三个条件的方式叫做:重写

B.发生运行时绑定的条件是:

1.先要向上转型 即父类的引用引用子类的对象

2.发生重写

注:程序编译的时候还是Animal的message方法,在运行时候绑定了Dog的message方法。

1.4 多态

父类引用 引用子类对象,通过父类引用调用父类和子类的同名覆盖方法。此时,如果父类引用 引用子类对象不一样,调用这个重写方法,表现的行为也是不一样的。

抽象类

1.1 抽象方法

  1. 抽象方法:使用abstract修饰方法,没有方法体,只有声明。定义的是一种规范,告诉子类必须要给抽象方法实现。

1.2 抽象类

  1. 抽象类不能使用new操作符创建他的实例

  2. 包含抽象方法的类,必须声明为抽象类

    //抽象类
    abstract class Shape{
        public int size;//可以有普通成员属性
        public Shape(){}//可以有构造方法
        abstract public void draw();//抽象方法
    }
    
  3. 抽象类的构造方法定义为protected,因为他只被子类使用,抽象类不能是private和final修饰的

  4. 一个普通类如果继承了抽象类,这个类需要重写这个抽象类当中的所有抽象方法。(如果这个子类不能实现所有的抽象方法,那么这个子类也必须定义为抽象的,且抽象方法是非静态的)

    abstract class Shape{
        abstract public void draw();
    }
    abstract class Rect extends Shape{
        abstract public void count();
    }
    class Triangle extends Rect{
      @Override  
      public void draw(){}
        @Override
        public void count() {}
    }
    
    • 这段代码中Rect继承了Shape,但是不能实现Shape所有的抽象方法,所以它定义为为abstract,而Triangle继承了Rect,所以Triangle要实现Rect和Shape所有抽象方法。

接口

1.1 interface

  1. 接口:只包含 常量和抽象方法

    • 接口当中的方法,没有具体实现
    • 接口当中的方法,默认全部都是public abstract
    • 接口当中的成员变量,都是public static final
    • 接口也是不能被实例化的(不能new)
  2. 接口的使用:implements

    interface IShape{
      public static final int num=10;
      //可以简写:int num=10;
        void draw();
      //默认是public abstract,可省
    }
    class Circle implements IShape{
        @Override
        public void draw() {
            System.out.println("o");
        }
    }
    public class TestInterfacs {
        public static void main(String[] args) {
            IShape iShape=new Circle();
            iShape.draw();
        }
    }
    
    • Cirle也必须实现接口IShape里面的抽象方法。
    • 继承只能继承一个,implements接口可以实现多个
    interface IA{
        
    }
    interface IB{
        
    }
    abstract class ID{
        
    }
    class IE extends ID implements IA,IB{
      //继承必须在接口实现的前面,就是extends必须写在implements前面。
    }
    

1.2 常用接口

  1. Comparable

    例题:给学生排序(如下方法排序有缺陷,因为将类写死了)

    class Student implements Comparable<Student>{
        public int age;
        public double scores;
        public String name;
    
        public Student(int age, double scores, String name) {
            this.age = age;
            this.scores = scores;
            this.name = name;
        }
        @Override
        public int compareTo(Student o) {
           //重写接口Comparable里面的方法
    //        if(this.age>o.age){
    //            return 1;
    //        }else if (this.age==o.age){
    //            return 0;
    //        }else{
    //            return -1;
    //        }
            //根据年龄排序简化写法:
    //        return o.age-this.age;//从大到小排序
    //        return this.age-o.age;//从小到大排序
    //				根据姓名排序:
            return this.name.compareTo(o.name); 
             //这是string里面的comperTo
        }
    }
    public class TestInterfacs2 {
        public static void main(String[] args) {
            Student s1=new Student(3,59,"zizi");
            Student s2=new Student(15,69,"zizi");
            int ret=s1.compareTo(s2);
            System.out.println(ret);
        }
    }
    
  2. Comparator:比较器

    //按照年龄排序
    class AgeComparator implements Comparator<Student> {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.age - o2.age;
            }
        }
    //按照分数排序
    class ScoreComparator implements Comparator<Student>{
           @Override
           public int compare(Student o1, Student o2) {
               return (int)(o1.scores-o2.scores);
           }
       }
    //按照年龄排序
    class NameComparator implements Comparator<Student>{
           @Override
          public String compare(Student o1, Student o2) {
               return o1.compareTo(o2);
           }
       }
    public static class TestInterfacs2 {
    public static void main(String[] args) {
              Student[] students = new Student[2];
              Student s1=new Student(3,59,"zizi");
              Student s2=new Student(15,69,"zizi");
    AgeComparator ageComp= new AgeComparator();
    ScoreComparator scoreComp = new ScoreComparator();
     NameComparator NameComp = new NameComparator();
              Arrays.sort(students, scoreComp); System.out.println(Arrays.toString(students));
            }
        }
    }
    

1.3 扩展

  1. extends扩展:T3扩展到了T2和T1的功能

    interface T1{}
    interface  T2 extends T1{}
    interface T3 extends T2{}
    

1.4 Clonable接口

  1. 空接口,标志接口:代表如果一个类实现了这个接口,证明这个类就可以被clone

    public interface Clonable{
    }
    
  2. class Money{
        public double money=19.9;
    }
    
    class Person implements Cloneable{
        public int age=99;
        public Money m=new Money();
        @Override
        protected Object clone() throws CloneNotSupportedException{
            return super.clone();
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "age=" + age +
                    ", m=" + m +
                    '}';
        }
    }
    public class TestMoney {
        public static void main(String[] args) throws CloneNotSupportedException{
            Person person=new Person();
            System.out.println(person);
    
            Person person1=(Person) person.clone();
        }
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值