• Java面向对象三大特性:继承、封装、多态


    java封装、继承、多态笔记

    1.包

    1.包的命名规则

    (1)只能包含数字、字母、下划线、小圆点.

    (2)不能用数字开头,

    (3)不能是关键字或保留字

    例如:

    demo.class.exec1 //错误class是关键字

    demo.12a //错误,以数字开头

    demo.ab12.oa // 对

    命名规范实例:

    一般是小写字母+小圆点(一般是com.公司名.项目名.业务模块名)

    比如:

    com.hspedu.oa.model;

    com.hspedu.oa.controller;

    举例:
    com.sina.crm.user//用户模块

    com.sina.crm.order//订单模块

    com.sina.crm.utils //工具类


    2.常用的包

    一个包下,包含很多的类,java中常用的包有:

    java.lang.* //lang包是基本包,默认引入,不需要再引入

    java.util.* //util包,系统提供的工具包,工具类,使用 Scanner

    java.net.* //网络包,网络开发

    java.awt.* //是做java的界面开发,GUI


    3.包引入的注意事项

    一个类中最多只有一个package

    package的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一个package

    2.访问修饰符

    1.基本介绍

    java提供四种访问控制修饰符号控制方法和属性(成员变量)的访问权限(范围)

    1.公开级别:用public修饰,对外公开

    2.受保护级别:用protected修饰,对子类和同一个包中的类公开

    3.默认级别:没有修饰符号,向同一个包的类公开

    4.私有级别:用private修饰,只有类本身可以访问,不对外公开

    在这里插入图片描述

    3.面向对象编程的三大特点:继承、封装和多态

    1.封装

    1.1 封装的定义

    封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。

    1.2 封装的实现步骤的三部曲

    1)将属性进行私有化private【不能直接修改属性】

    2)提供一个公共的(public)set方法,用于对属性判断并赋值

    public void setXxx(类型参数名){
    //set方法用来设置或者修改属性值
    //加入数据验证的业务逻辑属性=参数名;
    }
    
    • 1
    • 2
    • 3
    • 4

    3)提供一个公共的get方法,用于获取属性的值

    public XX getXxx(){//权限判断
    return xx;
    }
    
    • 1
    • 2
    • 3
    1.3封装快速入门案例

    案例一:

    不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。

    年龄合理就设置,否则给默认‘年龄必须在1-120,年龄,工资不能直接查看,name的长度在2-6之间

    package com.hspedu.encap;
    //不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认
    //年龄必须在1-120,年龄,工资不能直接查看,name的长度在2-6之间
    public class Encapsulation {
        public static void main(String[] args) {
            Person person = new Person();
            person.name="li";
            person.setAge(10);
            person.setSalary(10000);
            System.out.println(person.info());
        }
    }
    class Person{
        public String name;
        private int age;
        private double  salary;
    
        public void  setName(String name){
            if(name.length() >=2 && name.length() <=10)
                this.name = name;
            System.out.println("不合法");
        }
        public void setAge(int age) {
            if(age < 1 || age > 120)
                System.out.println("年龄不符合条件");
            this.age = age;
        }
        public void setSalary(double salary) {
            this.salary = salary;
        }
        public String getName(){
            return name ;
        }
        public int getAge() {
            return age;
        }
        public double getSalary() {
            return salary;
        }
        //写一个方法返回字符串
        public String  info(){
            return "信息为 name="+name+"age="+age+"salary="+salary;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    案例二:

    创建程序,在其中定义两个类:Account和AccountTest类,体会Java的封装性。

    1.Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须>20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值

    2.通过setXxx的方法给Account的属性赋值。

    3.在AccountTest中测试

    提示知识点:
    String name= “”;int len = name.length();

    package com.hspedu.encap;
    
    public class Account{
        String name;
        double salary;
        String pass;
    
        public Account() {
        }
    
        public Account(String name, double salary, String pass) {
            this.name = name;
            this.salary = salary;
            this.pass = pass;
        }
    
        public String getName() {
            return name;
        }
    
        public double getSalary() {
            return salary;
        }
    
    
        public void setName(String name) {
            if(name.length() == 2 || name.length() == 3 || name.length() == 4)
                this.name = name;
        }
    
        public void setSalary(double salary) {
    
            if(salary >= 20){
                this.salary = salary;
            }else {
                this.salary = 0;
            }
    
    
        }
    
        public void setPass(String pass) {
            if(pass.length() == 6)
                this.pass = pass;
            else {
                System.out.println("密码错误");
                this.pass = "000000";
            }
    
        }
    
        public String getPass() {
            return pass;
        }
    
        public void showInfo(){
            System.out.println("name =" + name + "salary =" + salary + "pwd =" + pass);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    package com.hspedu.encap;
    
    public class AccountTest {
        public static void main(String[] args) {
            Account account = new Account();
            account.setName("ping");
            account.setSalary(13);
            account.setPass("123456");
            account.showInfo();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.继承

    1.继承的基本介绍和示意图

    继承可以解决代码复用,让我们的编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父

    类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。

    画出继承的示意图

    在这里插入图片描述

    2.继承的基本语法
    class 子类 extends 父类{}
    
    • 1

    1)子类就会自动拥有父类定义的属性和方法

    2)父类又叫超类,基类。

    3)子类又叫派生类。

    3.重点理解

    1.子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过公共的方法去访问

    拆分

    (1)子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,除了父类中的私有方法继承后无法使用,其与方法都可以使用

    父类

    package com.hspedu.extend_.improve;
    //父类,是pupil和graduate的父类
    public class Student {
        //共有的属性
        public String name;
        private  double score;
        public int age;
    	//共有的方法
        public void setScore(double score) {
            this.score = score;
        }
        public void showInfo(){
            System.out.println(age + "岁的" + name + "考试考了" + score);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    子类:假设只有显示的某个信息不一样,这个信息是子类特有的

    package com.hspedu.extend_.improve;
    public class Pupil extends Student {
        
        public void testInfo(){
            System.out.println("小学生" + name + "正在考小学数学");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    package com.hspedu.extend_.improve;
    
    public class Graduate  extends Student{
    
        public void testInfo(){
            System.out.println("大学生"+ name + "正在考大学数学");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试

    package com.hspedu.extend_.improve;
    
    public class Test {
        public static void main(String[] args) {
            Pupil pupil = new Pupil();
            pupil.name="li";
            pupil.age = 10;
            pupil.setScore(100);
            pupil.testInfo();
            pupil.showInfo();
            System.out.println("==============");
            Graduate graduate = new Graduate();
            graduate.name = "ping";
            graduate.age = 20;
            graduate.setScore(98);
            graduate.testInfo();
            graduate.showInfo();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    (2)但是私有属性和方法不能在子类直接访问

    刚才的年龄是共有属性

    //如果把父类中年龄改成私有的
    private int age;
    
    //测试中的这一行代码会出错
      pupil.age = 10;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (3)解决上述问题:要通过公共的方法去访问

    package com.hspedu.extend_;
    
    public class Base {
        //不同的属性
        public int n1 = 100;
        protected int n2 = 200;
        int n3 = 300;
        //n4是私有的,Sub无法直接拿到
        private  int  n4 = 400;
        //父类中提供了一个public的方法,返回了n4,通过这个方法,Sub类中就可以拿到n4的参数
        public int getN4() {
            return n4;
        }
        //无参构造器
        public Base(){
            System.out.println("父类的无参构造器Base()被调用....");
        }
        //不同的属性
        public void Base1(){
            System.out.println("Base1()...");
        }
        void Base02(){
            System.out.println("Base2()...");
        }
        protected void  Base03(){
            System.out.println("Base03()...");
        }
        //在Sub中是无法获取的
        private void Base4(){
            System.out.println("Base4()....");
        }
        //可以通过这个方法来实现
        public void callBase4(){
            Base4();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    测试

    package com.hspedu.extend_;
    
    public class Sub extends  Base{
         public Sub(){
    //         super();//默认调用父类的无参构造器,写不写都会被调用
             System.out.println("子类的无参构造器Sub()被调用...");
         }
         public void ok(){
             System.out.println("n1:"+ n1+ "\t n2:" + n2 + "\t n3:" + n3);
             //由于Base下的n4是私有的,因此无法直接拿到,但是可以将私有的属性通过共有的方法让继承后类中使用
    
             System.out.println("n4:"+getN4());
             Base1();
             Base02();
             Base03();
             //Base4的方法是私有的无法拿到,但是可以通过共有的方法那它在传到当前位置来
             //Base4();
             //在Base中使用了公共方法将其传入
             callBase4();
    
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.子类必须调用父类的构造器,完成父类的初始化

     //尽管Sub类中的方法没有调用父类的无参构造器,但是也会显示父类无参构造器相关信息,然后显示子类的无参构造器相关信息
    
    • 1
    //上面代码的片段
    public class Sub extends  Base{
         public Sub(){
    //         super();//默认调用父类的无参构造器,写不写都会被调用
             System.out.println("子类的无参构造器Sub()被调用...");
         }
    
         public Sub(String name ){
             System.out.println("子类有参构造器Sub(String name )被调用");
    
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试:
    在这里插入图片描述

    3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在

    子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过[举例说明]

    package com.hspedu.extend_;
    
    public class Extendtail {
        public static void main(String[] args) {
    
            //尽管Sub类中的方法没有调用父类的无参构造器,但是也会显示父类无参构造器相关信息,然后显示子类的无参构造器相关信息
            Sub sub = new Sub();
            System.out.println("============");
            Sub sub1 = new Sub();
    //       sub.ok();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试结果:默认父类无参构造器会被调用

    在这里插入图片描述


    指定调用构造器

    public class Base {
        
        //无参构造器
    //    public Base(){
    //        System.out.println("父类的无参构造器Base()被调用....");
    //    }
        public  Base(String name, int age){
            System.out.println("用的是父类第二个Base(String name, int age)");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public class Sub extends  Base{
         public Sub(){
    //         super();//默认调用父类的无参构造器,写不写都会被调用
             //当父类的无参构造器被覆盖时,需要指定
             //super在使用时,必须放在构造器的第一行
             //super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器里面,第一行写了super(),就不能写this()
             super("li",10);
             System.out.println("子类的无参构造器Sub()被调用...");
         }
    
         public Sub(String name ){
               //当父类的无参构造器被覆盖时,需要指定
             super("chen",24);
             System.out.println("子类有参构造器Sub(String name )被调用");
    
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    4.如果希望指定去调用父类的某个构造器,则显式的调用一下: super(参数列表)

    5.super在使用时,必须放在构造器第一行(super)

    6.super()和 this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

    7.java所有类都是Object类的子类,Object是所有类的基类.

    8.父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)

    9.子类最多只能继承一个父类(指直接继承),即java中是单继承机制。

    思考:如何让A类继承B类和C类?

    答案:A继承B,B在继承C

    继承的本质:

    /*
    * (1)先查看子类是否有该属性
    * (2)如果子类有该信息,并且可以访问,则返回信息
    * (3)如果子类没有该属性,就看父类有没有这个属性,如果父类有该属性,并且可以访问,则返回父类的该信息
    * (4)如果父类的该属性不可以访问,继续找上一级的父类,直到找到object
    * */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    问题:如果对象son要访问age这一属性,但是父类Father的age是私有的,爷爷类Grandpa的age是共有的,那么他能拿到爷爷的age吗?

    不能!因为son在访问Father类的时候已经找到age这一 个属性了,但是由于是私有的无权访问,拿不到结果。它已经找到了,就不在想上找了,不会说无权访问就直接拿到grandpa类中的age属性。

    4. super关键字

    super代表父类的引用,用于访问父类的属性、方法、构造器

    ●基本语法

    1.访问父类的属性,但不能访问父类的private属性【案例】 super.属性名;

    2.访问父类的方法,不能访问父类的private方法【案例】super.方法名(参数列表);

    3.访问父类的构造器(这点前面用过):super(参数列表);只能放在构造器的第一句,只能出现一句!

    在这里插入图片描述
    Super关键字
    1.调用父类的构造器的好处(分工明确父类属性由父类初始化,子类的属性由子类初始化)
    2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果!
    3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。A->B->C,当然也需要遵守访问权限相关的规则

    5.Super和this关键

    在这里插入图片描述

    3. 重写/覆盖

    简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法

    1.子类的方法的参数,方法名称,要和父类方法的参数,方法名称完全一样。

    2子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类

    比如父类返回类型是Object ,子类方法返回类型是String

    【演示】

    public class Animal {
        public void ask(){
            System.out.println("动物在叫唤.....");
        }
        public Object m1(){
            return null;
        }
    }
    public class Dog extends Animal {
    
        public void cry(){
            System.out.println("wangwang......");
        }
        //和public object m1()构成重写
        public String m1(){
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    【练习一】:

    1.编写一个Person类,包括属性 private (name、age),构造器、方法say(返回自我介绍的字符串)。
    2.编写一个Student类,继承Person类,增加id、score属性private,以及构造器,定义say方法(返回自我介绍的信息)。
    3.在main中,分别创建Person和Student对象,调用say方法输出自我介绍。
    体会在子类中使用super()的好处
    1.Person类,父类

    package com.hspedu.override_;
    public class Person {
        private  String name;
        private int age;
        
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String  say(){
            return "我的名字是"+ name + "年龄是:" + age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2.studen类

    package com.hspedu.override_;
    
    public class Student extends Person {
        private  int id;
        private  double score;
    
        public Student(String name, int age, int id, double score) {
            super(name, age);
            this.id = id;
            this.score = score;
        }
        public String say(){
            return super.say() + "id= "+ id + "score = " +score;
        }
        public void setId(int id) {
            this.id = id;
        }
    
        public void setScore(double score) {
            this.score = score;
        }
    
        public int getId() {
            return id;
        }
    
        public double getScore() {
            return score;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3.测试

    package com.hspedu.override_;
    public class MainT {
        public static void main(String[] args) {
            Person person = new Person("li",18);
            System.out.println(person.say());
            System.out.println("====");
            Student student = new Student("li",18,2203,80);
            System.out.println(student.say());
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    知识点快速回顾
    接口自动化测试 —— 工具、请求与响应
    一种考虑时空关联的深度学习短时交通流预测方法
    IntelliJ IDEA 左侧Commit栏不见了
    Flume学习笔记:03-自定义拦截器
    ceph 009 管理定义crushmap 故障域
    nodejs+vue网上婚纱购物系统elementui
    【题解】NowCoder DP4 最小花费爬楼梯
    Leo赠书活动-07期 【嵌入式虚拟化技术与应用】文末送书
    能否帮我写个论文的框架。
  • 原文地址:https://blog.csdn.net/qq_41977843/article/details/128155501