程序笔记   发布时间:2022-07-19  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了「Java基础」六、面向对象 进阶大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

六、面向对象 进阶

封装继承多态-----------java三大特性

  • 类、接口间关系
    • 类 与 类 之间是:单根继承
    • 类 与 接口 之间是:多实现
    • 接口 与 接口 之间是:多继承

1 - 封装

核心只对需要的类可见用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象

同时也是为了减少代码冗余

特性

​ 安全特性;

便于使用特性;

​ 提供重复性的特性;

好处

  1. 隐藏信息和实现细节

通过控制访问权限可以将不希望客户端程序员看见的信息隐藏起来(如客户的银行密码需要保密,便需要只对客户开放权限)

  1. 实现了专业的分工

将能实现某一特定功能的代码封装成一个单独的类,在程序员需要使用的时候可以随时调用,从而实现了专业的分工

  1. 提高对象数据的安全性
  • 如果不使用封装,很容易赋值错误,并且任何人都可以更改,造成信息的不安全
  • 封装以后,设置类的属性为private(关键字),不能使用对象名.属性名的方式直接访问对象的属性,提高了其安全性。
  • 封装时,类的属性private类的方法public

1 - 1 成员的访问权限

private default protected public
同一个类 可用 可用 可用 可用
同一个包中的类 可用 可用 可用
子类 可用 可用
其他包中的类 可用

2 - 继承(extends)

将多个类具有共同特征和行为封装成一个类,实现一次定义,减少代码冗余,实现了代码复用

一个拥有自己独特特征的类(子类 扩展类) 继承(extends) 拥有共同特征的类(父类 基类)

子类继承父类,拥有父类的属性,因而子类的对象可以给共同属性赋值

java中一个类只能继承一个类(单根继承)

继承是一个很普遍的现象

如果一个类明确指明了继承(extends)自某一个类,则这个类就是他的父类

如果一个类并未通过extends指明继承自某一个类,则这个类继承自Object类(顶级父类---最大的类)

public class Animal { // 父类
    private String name;
    private int age;

    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;
    }
    
    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }

}
public class Dog extends  Animal{ // 子类
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String typE) {
        this.type = type;
    }
    
    @Override
    public String toString() {
        return "Dog{" +
                "type='" + type + ''' +
                "} " + super.toString();
    }

}
public class Cat extends Animal{
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "address='" + address + ''' +
                "} " + super.toString();
    }
}
public class Main { // 测试类
    public static void main(String[] args) {
        Cat cat = new Cat();
        // 共同特征(通过继承获取)
        cat.setName("Hello KiTi"); 
        cat.setAge(3);
        // 独有特征
        cat.setAddress("北京");
        System.out.println(cat);
        
        Dog dog  = new Dog();
        // 共同特征(通过继承获取)
        dog.setName("旺财");
        dog.setAge(4);
        // 独有特征
        dog.setType("拉布拉多");
        System.out.println(dog);

    }
}

3 - 多态

同一个行为具有多个不同的表现形式。

封装和继承多态表现形式

多态实现三个充要条件

  1. 继承
  2. 重写父类方法
  3. 父类引用指向子类对象
  • 此处Fruit apple = new Apple();父类的引用指向子类的对象,这便是多态的一种体现(向上转型),因为Apple继承与Fruit并重写了eatFruit(),所以能够表现多种状态的形式。

  • 向上转型小范围 ------> 大范围

    Fruit apple = new Apple();

  • 动态绑定(自动实现的)

    向上转型后,用父类的变量接收子类的对象(Fruit apple = new Apple();),运行时会找父类类型变量(apple)中存放数据的实际类型(Apple()),并执行这个实际类(Apple())中的对应方法(eatFruit()),而不是父类(Fruit)中的方法(eatFruit()),用static修饰可以解决此问题

/**
 * 水果
 */
public class Fruit {
    String fruit; // 

    public String getFruit() {
        return fruit;
    }

    public void setFruit(String fruit) {
        this.fruit = fruit;
    }

    public void eatFruit(){
        System.out.println("吃水果!");
    }

    @Override
    public String toString() {
        return "Fruit{" +
                "fruit='" + fruit + ''' +
                '}';
    }
}
/**
 * 苹果
 */
class Apple extends Fruit{

    private String color;   // 颜色

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + ''' +
                "} " + super.toString();
    }

    @Override
    public void eatFruit(){
        color = "红色";
        super.fruit = "苹果";
        System.out.println("吃" + color + fruit);
    }

}
/**
 * 橙子
 */
class Orange extends Fruit{
    private String exterior;   // 外观

    public String getExterior() {
        return exterior;
    }

    public void setExterior(String exterior) {
        this.exterior = exterior;
    }

    @Override
    public void eatFruit() {
        exterior = "圆的";
        super.fruit = "橘子";
        System.out.println("吃" + exterior + fruit);
    }

    @Override
    public String toString() {
        return "Orange{" +
                "exterior='" + exterior + ''' +
                "} " + super.toString();
    }
}

3 - 1 向上转型的应用场景

向上转型会隐藏子类扩展出来的功能

public class Test {
    // 将参数列表改为各种水果的父类,只需要定义一次,就可以重复利用,而不需要利用方法重写来实现同一个动作
    public static void DoThing(Fruit fruit){
        System.out.println("---------------------------------------");
        fruit.eatFruit();
        System.out.println("---------------------------------------");
    }
//--------------------方法重写,会导致代码冗余--------------------
    /*public static void DoThing(Orange orangE){
        System.out.println("---------------------------------------");
        fruit.eatFruit();
        System.out.println("---------------------------------------");
    }
    public static void DoThing(Apple applE){
        System.out.println("---------------------------------------");
        fruit.eatFruit();
        System.out.println("---------------------------------------");
    }*/
//--------------------------------------------------------------

    }

    public static void main(String[] args) {

        DoThing(new Apple());
        DoThing(new Orange());

    }
}

3 - 2 向下转型

大范围 -----> 小范围 (强制类型转换):把父类说成子类

向下转型要求:父类必须拥有子类的属性不能拥有就会出现类型转换异常

Apple apple = (ApplE) new Fruit();

  • 向下转型的应用场景

    明确知道了传入的数据是什么类型,才能进行向下转型

    如果要进行向下转型,必须先向上转型,在向下转型,不然会出错

    public class Test {
        
        public static void main(String[] args) {
            
    //        Apple apple = (ApplE) new Fruit(); // 单纯的进行强制类型转换会出现异常
            
            Fruit fruit = DoThing(1);
    
            if (fruit instanceof OrangE){
                Orange orange = (OrangE) fruit;
                System.out.println(orangE);
            }else{
                Apple apple = (ApplE) fruit;
                System.out.println(applE);
            }
    
        }
    
        public static Fruit DoThing(int number){
            
            if (number == 0){
                Orange orange = new Orange();
                orange.setFruit("橘子");
                orange.setExterior("圆的");
                return orange;
            }else{
                Apple apple = new Apple();
                apple.setFruit("苹果");
                apple.setColor("红色");
                return apple;
            }
        }
    
    }
    

4 - 组合

组合就是将对象引用置于新类中。

组合也是一种提高代码复用性的方式。

如果你不想类有更多扩展功能,你需要记住一句话多用组合,少用继承

  • 组合和继承是有区别的

    特征 组合 继承
    关系 组合是一种has - a的关系,可以理解为有一个 继承是一中 is - a 的关系,可以理解为是一个
    耦合性 组合是一种松耦合的关系 继承双方紧耦合
    是否具有多态 组合不具备多态和向上转型 继承是多态的基础,可以向上转型
    时期 组合是运行期绑定 继承是编译期绑定
  • Fruit类引用了Apple类、Orange类,从而调用他们各自的属性和方法

public class Test{
    
    public static void main(String[] args) {
        
        Fruit fruit = new Fruit();
        fruit.setFruit("苹果"); 

        Apple apple = new Apple();
        apple.setColor("红的");
        fruit.setApple(applE);

        Orange orange = new Orange();
        orange.setExterior("圆的");
        fruit.setOrange(orangE);

        System.out.println(fruit);
        
    }
}
/**
 * 水果
 */
public class Fruit {
    private String fruit;

    private Apple apple;
    private Orange orange;

    public Apple getApple() {
        return apple;
    }

    public void setApple(Apple applE) {
        this.apple = apple;
    }

    public Orange getOrange() {
        return orange;
    }

    public void setOrange(Orange orangE) {
        this.orange = orange;
    }

    public String getFruit() {
        return fruit;
    }

    public void setFruit(String fruit) {
        this.fruit = fruit;
    }

    public void eatFruit(){
        System.out.println("吃水果!");
    }

    @Override
    public String toString() {
        return "Fruit{" +
                "fruit='" + fruit + ''' +
                ", apple=" + apple +
                ", orange=" + orange +
                '}';
    }
}

/**
 * 苹果
 */
class Apple{

    private String color;   // 颜色

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + ''' +
                '}';
    }
}

/**
 * 橙子
 */
class Orange{
    private String exterior;   // 外观

    public String getExterior() {
        return exterior;
    }

    public void setExterior(String exterior) {
        this.exterior = exterior;
    }


    @Override
    public String toString() {
        return "Orange{" +
                "exterior='" + exterior + ''' +
                '}';
    }
}

5 - 接口和抽象类

5 - 1 接口(interface)

因为接口不能被实例化,故接口不能有任何构造方法

如果一个事务只有共同行为(功能)没有共同特征(属性),则用接口定义

接口注重功能,所以接口中只有方法,且默认为抽象方法(即默认是用public abstract修饰的)

接口可以多实现(implements)

// 定义接口
public interface Shape { 
    void area();    // 计算面积
    void perimeter();   // 计算周长
}
// 实现接口
public class Circle implements Shape {

    @Override
    public void area() {
        System.out.println("计算Circle的面积");
    }

    @Override
    public void perimeter() {
        System.out.println("计算Circle的周长");
    }
}

5 - 1 - 1 接口实现解耦合

耦合:个体相互之间有依赖关系

好处:

  1. 便于修改
  2. 业务并行
  3. 分工协作
  4. 通用性强(低耦合)
public class Test {
    public static void main(String[] args) {
        
        Computer computer = new Computer();
        
        computer.setMainBoard("I7 的主板"); // 同一块主板可以使用不同的cpu

        computer.setCpu(new I3());
        computer.getCpu().jiSuan();//调用i3主板的计算功能

        computer.setCpu(new I5());
        computer.getCpu().jiSuan();//i5主板的计算功能

        computer.setCpu(new I7());
        computer.getCpu().jiSuan();//i7主板的计算功能
    }

}
public class Computer {
    private String mainBoard; //主板
    private Cpu cpu; // 相当于电脑预留了一个cpu接口,可以安装任意版本

    public String getMainBoard() {
        return mainBoard;
    }

    public void setMainBoard(String mainBoard) {
        this.mainBoard = mainBoard;
    }

    public Cpu getCpu() {
        return cpu;
    }

    public void setCpu(Cpu cpu) {
        this.cpu = cpu;
    }


    @Override
    public String toString() {
        return "Computer{" +
                "mainBoard='" + mainBoard + ''' +
                ", cpu=" + cpu +
                '}';
    }
}

public interface Cpu {    void jiSuan(); // cpu的计算功能}class I3 implements Cpu{    @Override    public void jiSuan() {        System.out.println("I3 Cpu 的计算功能!");    }}class I5 implements Cpu{    @Override    public void jiSuan() {        System.out.println("I5 Cpu 的计算功能!");    }}class I7 implements Cpu{    @Override    public void jiSuan() {        System.out.println("I7 Cpu 的计算功能!");    }}

5 - 2 抽象类(abstract)

抽象类约束没有接口严格,抽象类中可以定义 构造方法、抽象方法、普通属性、普通方法、静态属性和静态方法

抽象方法一定存在于抽象类中,但抽象类中不一定有抽象方法,也可以有具体的方法

抽象类不能创建对象Fruit fruit = new Fruit()会报错)

public abstract class Fruit{ // 父类,此时父类也是抽象类
    private String fruit;
    
    public String getFruit();

    public void setFruit(String fruit) {
        this.fruit = fruit;
    }

    public abstract void eatFruit(); // 抽象方法
}

class Apple extends Fruit{ // 子类
    private String color;
    
	public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
    
    @Override
    public void eatFruit() { // 必须要添加父类中的行为,否则会报错
        System.out.println("吃"+color+"苹果!");
    }
}

6 - static

在方法区中会独立分配一块空间用来存放static修饰的数据,static修饰的东西都会存入其中,并且其中的数据是通用的

java中的关键字-----静态的

可以修饰属性和方法

static用在没有创建对象时调用方法/属性

  • 静态成员变量

    可以修饰全局变量,不能修饰局部变量

    class test{    public static String name = "码农"; // 可以修饰全局变量(类变量)        public void Do{		static String name2 = "码羊"; // 报错,不能修饰局部变量    }    }
    
  • 静态方法

    可以使用类名.方法名调用

    static不能修饰 get方法、set方法、构造方法、抽象方法、类

    同一个类中调用类方法,可以省略类名

    静态方法中 ** 不能访问 非静态方法非静态成员变量**

    public class Circle implements Shape {
    
        private static Double PI = 3.14; // 静态成员变量
        privatE int r; // 非静态成员变量
    
        // 静态方法
        public static void area2(){
    //        2*PI*r;  // 报错,因为此为静态方法,而r为非静态成员变量
        }
    
        @Override
        public void area() {
            System.out.println(PI*r*r);
        }
    
        @Override
        public void perimeter() {
            System.out.println("计算Circle的周长");
        }
    
    }
    
  • 静态代码快

    用于类的初始化操作,进而提示程序性能

    静态代码块随着类的加载而执行,因此,很多时候会 只需要 执行一次的初始化操作放在static代码块中进行

    public class StaicBlock {
        static{
        	System.out.println("I'm A static code block");
        }
    }
    

7 - final

最后的,最终的

可以修饰类、属性(全局变量和局部变量)、方法

  • final修饰类时

    一旦修饰,表示此类不能被继承

    成员变量可以根据需要设定为final

    注意final中的所有成员方法会隐式的指定为final方法

  • final修饰方法时

    修饰方法时,表示此方法不能被子类重写

    只有在明确不希望此方法被子类重写时才会将其设定为final

  • final修饰变量时

    final没有优先分配的功能所以必须对其进行赋值(可以使用构造代码块对其进行赋值,因为构造代码块会在构造方法前执行,且调用几次构造方法,便加载几次构造代码块

    • 修饰基本数据类型

      表示数据类型的值 不能 被改变

      public class Circle implements Shape {
      
          private static Double PI = 3.14;
          private static final Double PII = 3.14;
      
          public static void main(String[] args) {
              PI = 4.5; // 可以正常修改
      //        PII = 3.5; // 报错
          }
      }
      
    • 修饰引用数据类型时

      表示对其初始化后便 不能 在指向另一个对象

      public class Test {
          public static void main(String[] args) {
              final Fruit fruit = new Fruit();
              fruit.setFruit("苹果");
              fruit = null; // 报错:CAnnot assign a value to final variable 'fruit'
          }
      }
      
      class Fruit{
          private String fruit;
          
          public String getFruit() {
              return fruit;
          }
      
          public void setFruit(String fruit) {
              this.fruit = fruit;
          }
      }
      

大佬总结

以上是大佬教程为你收集整理的「Java基础」六、面向对象 进阶全部内容,希望文章能够帮你解决「Java基础」六、面向对象 进阶所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。