Java---封装,继承,多态,接口

目录

1.访问限定符

2.包

1.概念:

2.命名规则:

3. 常见的包

3.封装(encapsulation):

1.概念:

2.封装实现步骤

【封装例题】

4.继承

1 继承的语法

2.继承细节

3.继承的本质

 4.super关键字

5.fifinal 关键字

6.方法重写

5.多态

1.向上转型

2.向下转型

3.动态绑定机制

4.equals方法

5.abstract修饰抽象类

6.接口

7.接口优先原则


1.访问限定符

范围private默认protectedpublic
1同一个包中的同一个类YesYesYesYes
2同一个包中的不同类YesYesYes
3不同包中的子类YesYes
4不同包中的非子类Yes

注意:修饰符可以用来修饰类中的属性,成员方法以及类(类只能用默认和public修饰)

2.包

1.概念:

为了更好的管理类,把多个类收集在一起成为一组,称为软件

2.命名规则:

只能包含数字,字母,下划线,小圆点,不能数字开头,不能是关键字或保留字

3. 常见的包

java中只能导入某个包下的某个具体的类

1. java.lang: 系统常用基础类 (String Object), 此包从 JDK1.1 后自动导入。
2. java.lang.reflflect:java 反射编程包 ;
3. java.net: 进行网络编程开发包。
4. java.sql: 进行数据库开发的支持包。
5. java.util: java 提供的工具程序包。 ( 集合类等 ) 非常重要
6. java.io:I/O 编程开发包。

3.封装(encapsulation):

1.概念:

将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口(方法)来和对象进行交互

2.封装实现步骤

1.属性私有化(private)

2.提供(public)set方法,用于对属性判断并修改

3.(public)get方法用于获取属性的值

【封装例题】

创建程序,在其中定义两个类:Account和AccountTest类体会Java的封装性。
1. Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须>20)
2.密码(必须是六位),如果不满足,则给出提示信息,并给默认值
3.通过setXxx的方法给Account 的属性赋值。
4.在AccountTest中测试

package practice_1_16;

import java.util.Scanner;

public class AccountTest{
    public static void main(String[] args) {
        Account test = new Account("王聪",10,"1234567");
//        test.setName("王聪");
//        test.setBalance(10);
//        test.setPassword("1234567");
        test.info();
    }

}

class Account{
    private String name;
    private int balance;
    private String password;

    public Account() {
    }

    public Account(String name, int balance, String password) {
        this.setName(name);
        this.setBalance(balance);
        this.setPassword(password);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length() >= 2 && name.length() <= 4){
            this.name = name;
        }else{
            System.out.println("名字长度不符合规范,默认为空");
            this.name = null;
        }
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        if(balance <= 20){
            System.out.println("余额小于20,不符合规范");
            return;
        }else{
            this.balance = balance;
        }
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        if(password.length() != 6){
            System.out.println("密码长度不符合要求,默认初始密码123456");
            this.password = "123456";
        }else {
            this.password = password;
        }
    }
    public void info(){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入密码查看:");
        String  password = sc.nextLine();
        if(password.equals(this.password)){
            System.out.println("密码输入正确");
            System.out.println("姓名="+this.name+"余额="+this.balance+"密码="+this.password);
        }else {
            System.out.println("密码输入错误,您没有权限查看");
        }
    }
}

4.继承

继承的语法

借助 extends 关键字:
修饰符 class 子类 extends 父类 {
        //...
}

2.继承细节

1.通过子类对象访问成员时,遵循就近原则(若在父类中找到的属性是private修饰,则直接报错)

2.子类继承了父类所有的属性和方法,但是私有属性不能在子类直接访问,要通过公共的方法去访问(子类不能直接调用,可以在父类中去写个方法间接调用)
3.子类必须调用父类的构造器,完成父类的初始化(构造器不会被继承,只会被调用)
4.当创建子类对象时,不管使用子类的那个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类构造器中用super()去指定使用父类的那个构造器完成对父类的初始化工作,否则,编译不会通过.
5.想调用那个构造器就用super()显式调用哪个(调用无参构造器可省略)
6.super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
父类Student
public class Student {
    public String name;
    public int age;
    private double score;

    //无参构造器
//    public Student() {
//    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public void setScore(double score){
        this.score = score;
    }
    public void info(){
        System.out.println("姓名="+this.name+"\t"+"年龄="+this.age+"\t"+"成绩="+this.score);
    }
}

子类Pupil

public class Pupil extends Student{
    public Pupil() {
        super("xiaojinli",8,90);
    }

    public void testing(){
        System.out.println("小学生"+name+"正在考小学数学");
    }
}

子类Graduate

public class Graduate extends Student{
    public Graduate() {
        super( "锦鲤",18,100);
    }

    public void testing(){
        System.out.println("大学生"+name+"正在考高等数学");
    }
}

测试类test01

public class test01 {
    public static void main(String[] args) {
        Pupil pupil = new Pupil();
        pupil.name = "小锦鲤";
        pupil.age = 6;
        pupil.setScore(60);
        pupil.testing();
        pupil.info();
        Graduate graduate = new Graduate();
        graduate.name = "锦鲤呀";
        graduate.age = 18;
        graduate.setScore(100);
        graduate.testing();
        graduate.info();
    }
}

7.Object是所有类的父类,父类的构造器调用不限于直接父类,将一直往上追溯到Object类

8.子类只能直接继承一个父类,子类和父类之间必须满足逻辑关系.

3.继承的本质

public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son();
        
    }
}
class GrandPa{//爷类
    String name = "大头爷爷";
    String hobby = "旅游";
}
class Father{
    String name = "大头爸爸";
    int age = 39;
}
class Son{
    String name = "大头儿子";
}

【内存分析】

 4.super关键字

1. 只能在 非静态方法 中使用
2. 在子类方法中, 用来访问父类的(不能访问被private修饰的)属性,方法,构造器.

3.this和super的区别就在于this从本类开始访问,super从父类开始访问

5.fifinal 关键字

fifinal 关键可以用来修饰变量、成员方法以及类。
1. 修饰变量或字段,表示常量 ( 即不能修改 ),
    修饰引用数据类型,指的是其保存的地址不可改变
2. 修饰类:表示此类不能被继承
3. 修饰方法:表示该方法不能被重写

6.方法重写

1.方法重写就是子类中有一个方法,和父类中的某个方法的名称,参数完全一样

返回类型相同或者是父类返回类型的子类,子类方法不能缩小父类方法的访问权限

2.重载和重写的比较

 【举例】

public class OverrideExercise01 {
    public static void main(String[] args) {
        Person person = new Person("wang",18);
        System.out.println(person.say());
        Student1 student = new Student1("wang",18,10001,100);
        System.out.println(student.say());
    }
}
class Person{
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String say(){
        return "hello大家好我叫"+name+"我今年"+age+"岁了";
    }
}
class Student1 extends Person{
    private int id;
    private double score;

    public Student1(String name, int age, int id, double score) {
        super(name, age);
        this.id = id;
        this.score = score;
    }

    public String say(){
        return super.say()+"我的学号是"+id+"我的成绩是"+score;
    }
}

5.多态

1.向上转型

1. 必须在继承体系下
2.本质:父类的引用指向了子类的对象
3.语法:父类类型  引用名 = new 子类类型();
4.特点:编译类型看左边,运行类型看右边,可以调用父类中的所有成员(需要遵守访问权限)
不能调用子类中的特有成员,

【举例】

public class Animal {
    String name;
    int age = 19;
    public void sleep(){
        System.out.println("睡");
    }

    public void run(){
        System.out.println("跑");
    }

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

    public void show(){
        System.out.println("hello,你好啊,祝你平平安安");
    }
}
public class Cat extends Animal{

    int age = 18;

    public void eat(){
        System.out.println("小猫吃鱼");
    }

    public void catchMouse(){
        System.out.println("小猫抓老鼠");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.name = "小猫";
        animal.eat();
        animal.show();
        animal.sleep();
        animal.run();
    }
}
【原因分析】
由编译类型看左边,运行类型看右边可知,在编译过程中,通过的方法由animal中的eat(),sleep(),show(),run(),所以其不可访问Cat子类中特有的对象catchMouse(),而在运行阶段,运行到eat()方法时会首先在子类中开始找,这里在子类中找到了,所以就直接运行子类中的eat(),
(可以说子类中的eat()方法骗过了编译)

2.向下转型

1.向上转型后无法调用子类特有的方法,此时可以再通过向下转型来调用,

2.语法:子类类型 引用名 = (子类类型)父类引用(父类引用必须指向当前目标类型的对象)

3.向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入 了 instanceof ,如果该表达式为true,则可以安全转换。

instanceof()用来判断对象的运行类型是否为XX类型或其子类型

4.属性没有重写之说,属性的值看编译类型,方法的调用看运行类型

【以上述代码为例】

public class Test {
    public static void main(String[] args) {
        //向上转型
        Cat cat1 = new Cat();
        Animal animal = cat1;
        //结果为true,animal和cat指向同一个对象,所以地址相同
        System.out.println(animal == cat1);
        animal.name = "小猫";
        animal.eat();
        animal.show();
        animal.sleep();
        animal.run();
        //属性的值看编译类型
        System.out.println(animal.age);//19
        //向下转型
        //判断是否能转
        if(animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }
}

3.动态绑定机制

1.当调用对象方法时,该方法会和该对象的运行类型/内存地址绑定

2.当调用对象属性时,没有动态绑定机制,哪里声明就在哪里使用

3.总的来说就是(每一次的)调用方法都从运行类型开始找,而属性的值则是在哪个类里使用,就用哪个类的值

4.equals方法

== 和 equals的对比

1.==是一个比较运算符,在判断基本运算类型时,判断的是值是否相等

  判断引用类型时,判断的是地址是否相等,即判定是不是同一个对象.

2.equals方法只能判断引用类型,默认是判断地址,但子类往往会重写该方法

5.abstract修饰抽象类

1.抽象类比普通类多一些抽象方法(0-n),抽象方法没有方法体,只有方法声明

只有方法声明的还有一类方法称为本地方法,使用native关键字声明

2.抽象类必须有子类,只能通过子类向上转型实例化

3.抽象类不一定有抽象方法,抽象方法一定在抽象类中

4.普通子类继承抽象方法,必须重写抽象类中所有抽象方法

5.抽象子类继承抽象方法,选择重写抽象方法即可

6.abstrsct不可和private或final关键字一起使用

【】如果要求子类必须重写父类的某个方法,则推荐使用继承类

public abstract class Abstract01 {
    public String name;
    public int age;

    public Abstract01(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public abstract void test01();


}

class Abstract02 extends Abstract01{

    public Abstract02(String name, int age) {
        super(name, age);
    }
    public void test01(){
        System.out.println("这是父类抽象方法的重写");
    }

    public void test02(){
        System.out.println("这是子类特有的方法");
    }

}

class Test02{
    public static void main(String[] args) {
        Abstract01 abstract01 = new Abstract02("锦鲤",20);
        abstract01.test01();
        if(abstract01 instanceof Abstract01){
            Abstract02 abstract02 = (Abstract02) abstract01;
            abstract02.test02();
        }
    }
}

6.接口

1.接口中只存在全局常量和抽象方法,接口中不存在构造方法与普通方法

使用interface关键字,接口命名规范,使用大写的i开头

2.接口的普通子类必须重写接口中所有抽象方法,

  若普通子类同时实现多个接口,则必须重写接口中的全部方法

  接口不能继承类,但是可以同时继承多个父接口

  普通子类先继承一个类,在实现一个或多个接口

3.使用implement关键字实现接口

4.接口子类命名以接口名称开头以Impl结尾

5.在接口中public static final abstract 全部省略

6.接口的实例化:子类向上转型

7.接口不能继承类,但是可以多继承父接口

public interface IMessage {

    //在接口中public static final abstract 全部省略
    //全局变量
    public static final String MSG = "test";
    //抽象方法
    public abstract void print();



}
interface IM02{
    void print02();
}
class MessageImpl extends Interfac01 implements IMessage,IM02{

    public void print03(){
        System.out.println("抽象类中抽象方法的重写");
    }
    public void print(){
        System.out.println(MSG);
    }

    public void print02(){
        System.out.println("接口方法的重写");
    }
}

class Test{
    public static void main(String[] args) {
        IMessage iMessage = new MessageImpl();
        iMessage.print();
        IM02 im02 = new MessageImpl();
        im02.print02();
        Interfac01 interfac01 = new MessageImpl();
        interfac01.print03();
    }
}

7.接口优先原则

开发中优先考虑使用接口 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值