java学习笔记(四)——面向对象编程

面向过程和面向对象

举个栗子理解一下这两个概念吧,设想一个场景: 你要去找某个学校的张三,当然首先你不是这个学校的,假设你也没有带手机,他也没有。
首先先用面向过程的思想分析一下: 你要去找这个同学,那首先你得知道他的姓名等信息,然后通过保安的登记之后进入学校
按照学校的教学区域分块指引或者自己询问遇到的人去找张三啦。
在利用面向对象的想法来分析一下,首先你要找的是这个学校的张三,那他的职业是什么呢?老师?学生?行政?确定职业以后,那就只需要在
符合职业的一群人中就找啦,如果知道张三的性别,那就从那就符合职业的人群中在筛选出符合性别条件的,此时范围已经比较小了,再利用姓名去排除
应该很快就能找到张三啦~

在上述例子的面向对象的思想中,我们是通过一类一类的去缩小范围去查找的,在面向对象编程中,类是一个很重要的概念。在Java中,
面向对象的本质: 以类的方式组织代码,以对象的方式组织封装数据。
从代码的层面分析,是先有类,再有对象,类是对象的模板,对象是类实例化之后的结果
从认识论层面分析: 应该是先有对象,再有类,类是在对象的基础上抽象出来的,就像是一群人,他们里面有一部分是老师,
一部分是学生,那么就可以将所有的老师归为一类,将所有的学生归为一类,剩余的人归为一类。
类有三大特性: 封装,继承,多态

类的方法

//    带有static标识符的是静态方法,是和类一起生成的

// 而不带有static称为是非静态方法,只有当类实例化后才会存在
// 所以在同一个类里,静态方法可以互相调用,而在静态方法直接调用非静态方法,必须重新实例化类
// 在非静态方法中可以调用非静态方法,不用重新实例化类
// 方法的重载: 名称相同,参数不同或者参数的类型不同

package createClass;

public class Method {
    
    

    public static void main(String[] args) {
    
    
//        test('aa'); 会报错

//        实例化之后再去调用就不会报错了
        Method method = new Method();
        method.test("test");
    }
    public void test(String name){
    
    
        System.out.println(name); // test
        test("aa","bb","cc"); // 3
        int [] temp = {
    
    1,2,3,4};
        test(temp); // 1,2,3,4
    }
    public void test(String ...name){
    
    
        System.out.println(name.length);
    }
    public static void  test(int[] arr){
    
    
        for (int item:arr) {
    
    
            System.out.println(item);
        }
    }

}

封装

封装是针对于类的属性,而与方法无关。利用private来实现内属性的私有,封装的目的是实现代码的高内聚,低耦合,通过对外部暴露一些接口或者方法实现对内部属性的操作。由于JS里面也有封装,理解这个概念在写一遍,熟悉下java的代码写法:

//封装一个student类,通过对外部暴露get/set方法,来操作内部属性,生成get/set时可以通过alt+ insert建来生成
package encapsulation;

public class Student {
    
    
//    private: 标识符,标识属性私有

    private String name;
    private int age;
    private char sex;

//    提供操作这些属性的方法,访问和操作
//    下文中的this指代的是当前的类

    public String getName() {
    
    
        return this.name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public void setAge(int age) {
    
    
        if(age > 120 || age< -1){
    
    
            return;
        }
        this.age = age;
    }

    public void setSex(char sex) {
    
    
        this.sex = sex;
    }

    public int getAge() {
    
    
        return age;
    }

    public char getSex() {
    
    
        return sex;
    }
}

引用如下:

//实例化一个student,通过get访问属性值,name的默认值为null,再通过set方法设置值以后,再调用get访问,他的值变为设置的值
//而再设置age的时候,由于再代码中加了判断,当age>120或者age< -1的时候,对内部的属性不去做任何操作,因此age的值依然时第一次调用age的值为3

```java
package encapsulation;

public class Demo {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.getName()); // null
        student.setName("梅子黄时雨");
        System.out.println(student.getName()); // 梅子黄时雨
        student.setAge(3);
        System.out.println(student.getAge()); // 3
        student.setAge(500);
        System.out.println(student.getAge()); // 3
    }
}

继承

继承的概念再js中也有,JS提供了比java更丰富的继承方式,通过原型、原型链、组合继承、寄生继承等方式,ES6中利用class和extends来实现继承的方式和java是挺像的。

继承的本质就是对一批类的抽象,对现有世界更好的建模。

继承表示的是类与类之间的一种关系,除此以外类和类的关系还有依赖、组合、聚合等。

继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类使用关键字extends来表示。

所有的类都是Object类的子类。写一段代码熟悉一下新的继承写法吧

封装只和属性有关!封装只和属性有关!封装只和属性有关!

package extendsClass;

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();
        student.test();
    }
}

// Person类
package extendsClass;

public class Person {
   
    private String name;
    private char sex;
    private int age;

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }


}

package extendsClass;
// student继承了person,会拥有person的属性和方法,如果person的属性是私有的,那么student将不能继承,就不能通过.的方式来访问了。
public class Student extends Person {
    
    
    public void test(){
    
    
        Student student = new Student();
        //System.out.println(student.name); // 会报错,需要通过类暴露的方法和接口去访问和操作属性
        System.out.println(student.getName()); // null
        System.out.println(student.getAge());  // 0
        student.setName("学生");
        System.out.println(student.getName()); //学生
    }
}

this,super和构造器

super调用父类的构造方法,必须在构造方法的第一行

super调用必须只能出现在子类的方法或者构造方法中

super和this不能同时调用构造方法

this本身指调用者这个对象,没有继承也可以使用,this默认调用本类的构造,而super指的是父类的构造

package extendsClass;

public class Person {
    
    
    public Person() {
    
    
        System.out.println("Person无参构造执行了");
    }

    protected String job ="person";

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

package extendsClass;

public class Student extends Person {
    
    
    private String job = "syudent";
//    先调用父类的无参构造,在调用子类的无参构造, super()
//    写了有参构造以后,无参构造必须显示定义
//    如果父类没有无参构造,那么子类也无法定义无参构造

    public Student() {
    
    
//        super(); 显示调用父类的构造,必须放在子类构造的第一行
        System.out.println("Student无参构造执行了");

    }


    //    私有的属性无法被继承
    public void test(String job){
    
    
        System.out.println(job); //total
        System.out.println(this.job); //student
        System.out.println(super.job); //person

        print(); //当前类的print方法 testAAa
        this.print(); //当前类的print方法 testAAa
        super.print();//父类的print方法 person
    }

    @Override
    public void print() {
    
    
//        super.print();
        System.out.println("testAAa");
    }
}

package extendsClass;

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();
        student.test("total");
    }
}

多态

统一方法可以根据发送对象的不同而采用多种不同行为的方式。
一个对象的实际类型是确定的,但是指向对象的引用的类型有很多。

多态是方法的多态,属性是没有多态的
父类和子类有联系,如果没有会报类型转换异常 classCastExpection!
存在的条件:继承关系,存在方法重写,父类的引用指向子类的对象 Father f1 = new son()

方法重写: static方法不能被重写,不属于实例
final修饰的方法也不能被重写
private修饰的方法也不能重写

package moreInstance;

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

package moreInstance;

public class Test {
    
    
    public static void main(String[] args) {
    
    
//        一个对象的实际类型是确定的

//    student调用的方法都是自身或者继承自Person的
        Student student = new Student();
//        可以指向的引用类型就不是确定的了
//        父类的引用指向子类
//        对象能执行哪些方法主要看左边的类型和右边的关系不大

//       student1不可以调用子类独有的方法
         Person student1 = new Student();

//
         Object student3 = new Student();

        student1.test(); //StudentTest
        student.test(); //StudentTest

        student.eat();
//        student2.eat(); 直接会报错

        ((Student)student3).eat(); //转为Student类
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44813858/article/details/129775767
今日推荐