JAVA面向对象三大特征知识汇总(韩顺平)

目录

一.封装

1.基本介绍

2.封装的优点

3.封装实现的步骤(三步)

4.入门案例

二.继承

1.基本介绍

2.继承的基本语法

3.继承的优点

4.快速入门案例

5.继承的使用细节

六.继承实质

三.多态

1.基本介绍

2.具体体现

3.对象的多态

4.多态的使用细节

5.instanceof比较操作符

6.动态绑定机制

7.多态数组的应用


一.封装

1.基本介绍

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

简而言之,就是对数据加以限制或进行保护,比如,需要调取对象private属性,可以通过设置验证码,对数据进行保护

2.封装的优点

1)隐藏实现细节

2)可以对数据进行验证,保证安全合理

3.封装实现的步骤(三步)

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

2)提供一个公共的(public)set方法,对属性进行判断和复制

public void setXxx (类型,参数名){Xxx 表示某个属性

加入数据验证或对数据进行赋值

属性 = 参数名}

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

public 数据类型 getXxx(){权限判断,Xxx某个属性

return xx;}

4.入门案例

不能随便查看工人的年龄,工资的隐私,并对设置的年龄进行合理的验证,年龄必须在0——120,名字长度2——6,工资不能直接查看

package 面向对象中级;

import java.util.Scanner;

public class encap{
    public static void main(String[] args) {

        Person person = new Person();

        person.setName("jack");
        person.setAge(30);
        person.setSalary(30000);


        System.out.println("请输入验证码查看工资");
        Scanner myscanner = new Scanner(System.in);
        int n = myscanner.nextInt();
     
        System.out.println(person.info(n));//验证码输入为123456时可以访问工资

    }
}


class Person{
    //封装
    public String name;
    private int age;
    private double salary;
    private String job;

    //怎么在主类给age salar 初始化
    public void setName(String name){
        if (name.length() >= 2 && name.length() <= 6) {
            this.name = name;
        }else {
            System.out.println("名字长度不对");
        }
    }
    public String getName(){
        return name;
    }//快捷键ALT + insert

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        //判断
        if (age >= 1&& age <= 120) {
            this.age = age;
        }else {
            System.out.println("年龄需在0——120,默认年龄10");
            this.age = 10;//给一个默认年龄
        }
    }

    public double getSalary(int n) {
        if (n == 123456) {
            return salary;
        }else{
            System.out.println("你的权限不够");
            return 0.0;
        }
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    //
    public String info(int n){
        return "信息为 name=" + name + " age="+age+" salary="+getSalary(n);
    }

二.继承

1.基本介绍

当多个类存在相同的属性(变量)和方法时,可以从这些类中,抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可

2.继承的基本语法

class 子类 extends 父类{

}

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

2)父类又叫超类,基类

3)子类又叫派生类

3.继承的优点

1)代码的复用性提高

2)代码的扩展性和维护性提高

4.快速入门案例

创建一个学生类

package 面向对象中级.inherit.improve;
//父类,是Pupil和Graduate的父类
public class Student {
    public String name;
    public int age;
    private double score;

    public void setScore(double score) {
        this.score = score;
    }

    public void showinfo(){
        System.out.println("学生名字="+name+" 年龄="+age+" 成绩="+score);
    }
}

添加pupil和graduate对象的特殊属性

package 面向对象中级.inherit.improve;

public class Pupil extends Student{//ctrl + h可以查看子类与父类的关系
    public void testing(){
        System.out.println("学生" + name + "正在考小学数学");
    }
}

package 面向对象中级.inherit.improve;

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

测试

package 面向对象中级.inherit.improve;

import 面向对象中级.inherit.Graduate;
import 面向对象中级.inherit.Pupil;
import 面向对象中级.inherit.detail.Sub;

public class Test {
    public static void main(String[] args) {

        面向对象中级.inherit.Pupil pupil = new Pupil();
        pupil.name = "小明-";
        pupil.age = 10;
        pupil.testing();
        pupil.setScore(60);
        pupil.showinfo();

        System.out.println("========");

        面向对象中级.inherit.Graduate graduate = new Graduate();
        graduate.name = "小黑";
        graduate.age = 20;
        graduate.testing();
        graduate.setScore(60);
        graduate.showinfo();

    }
}

结果

5.继承的使用细节

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

eg.

 //父类
//4 个属性
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;


//父类提供一个 public 的方法,返回了 n4
    public int getN4() {
        return n4;
    }


public void sayOk(){//非私有的属性和方法可以在子类直接访问
                        //但是私有属性和方法不能在子类直接访问
                        //可以间接在父类提供一个公共的方法访问n4
        System.out.println(n1 + " "+n2+" "+n3+" "+getN4());


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

public Sub() {
        System.out.println("sub()...");
    }
//若没调用,则调用super();//默认调用父类的无参构造器


3) 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则不会通过

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

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

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

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

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

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

若让A同时继承B和C类,可以让A继承B,B继承C

10) 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

eg.Cat is a Animal  即  可写成public class Cat extends Animal

六.继承实质

1) 首先看子类是否有该属性

2) 如果子类有这个属性,并且可以访问,则返回信息

3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)

4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...

 观察下列输出结果

System.out.println(son.name);//大头儿子
//System.out.println(son.age);//报错
System.out.println(son.getAge());//39
System.out.println(son.hobby);//旅游


class GrandPa { //爷类
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrandPa {//父类
String name = "大头爸爸";
private int age = 39;
public int getAge() {
return age;
}
}
class Son extends Father { //子类
String name = "大头儿子";
}

三.多态

1.基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

2.具体体现

 
A a = new A();
//体现出形参列表具有多种形态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));
//方法重写体现的多态
B b = new B();
a.say();
b.say();
 
 
class B { //父类
public void say() {
System.out.println("B say() 方法被调用...");
}
}
 
 
class A extends B {//子类
public int sum(int n1, int n2){//和下面 sum 构成重载
return n1 + n2;
}
public int sum(int n1, int n2, int n3){
return n1 + n2 + n3;
}
public void say() {
System.out.println("A say() 方法被调用...");
}
}

3.对象的多态

1)一个对象的编译类型和运行类型可以不一致

2)编译类型在定义对象时,就确定了,不能改变

3)运行类型时可以变化的

4)编译类型看定义时 = 号的左边,运行类型看 = 号的右边

重点理解编译类型和运行类型(可以看我转载的Java将子类对象赋值给父类对象的文章,讲的非常细致)

要理解编译类型和运行类型,首先我认为我们要弄清什么是编译,什么是运行。编译是声明对象的类型,分配属性,检查语法错误等;运行是,将对象加载内存(一般用new,反射也常用), 运行代码执行功能等。我们举个例子,我们有个Animal类,还有个Dog类,且Dog extends Animal,Animal animal = new Dog();这里的animal的编译类型时Animal,而运行类型是Dog,这句代码真正的对象其实是new Dog,而animal只是对对象的引用,如果大家实在不理解为什么Animal是编译类型,Dog是运行类型,给大家举个例子,一头披着羊皮的狼,它的本质肯定是狼,这是毋庸置疑的,但是它却占这羊的身体(内存空间),当它做一下行为(方法)时,比如吃草调用的就是羊的身体(内存空间),所以当我们调用animal的属性的时候就看它的父类,当我们调用方法时就把它看成子类(比如羊吃草),不知道各位读者能理解编译类型和运行类型,反正我是这样理解的(O^ ~ ^O)

若实在理解不了,就记住当我们用到它的方法时,我便把它看成子类对象;若用到它的属性时,我把它看成父类对象

 下面代码帮助大家理解,看看输出结果是什么?

package Polydetail;
 
public class Animal {
    String name = "动物";
    int age = 10;
    public void sleep(){
        System.out.println("睡");
    }
    public void run(){
        System.out.println("跑");
    }
    public void eat(){
        System.out.println("吃");
    }
 
}
 
 
package Polydetail;
 
public class Dog extends Animal{
    String name = "狗";
    public void eat(){
        System.out.println("吃鱼");
    }
}
 
package Polydetail;
 
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog();
 
        animal.run();
        animal.eat();
        System.out.println(animal.name);
    }
}

4.多态的使用细节

1)多态的前提:
两个对象(类)存在继承关系

2)向上转型
(相当于在四中举得Animal和Dog的例子)

a.本质:父类的引用指向子类的对象

b.语法:父类类型 引用名 = new 子类类型();

b.特点:编译类型看左边,运行类型看右边

                可以调用父类中所有成员(对象,方法...)(需要遵守访问权限)

                 不能调用子类中特有的成员

                最终运行效果看子类的具体体现

3.向下转型
a.语法 :子类类型 引用名 = (子类类型) 父类引用

b.只能强转父类的引用,不能强转父类的对象

c.要求父类的引用必须指向当前目标类型的对象

d.当向下转型后,可以调用子类类型中所有成员

看看下面代码的输出结果

package Detail01;
 
public class Animal {
    String name = "动物";
    int age = 10;
 
    public void sleep() {
        System.out.println("睡");
    }
 
    public void run() {
        System.out.println("跑");
    }
 
    public void eat() {
        System.out.println("吃");
    }
 
}
 
 
package Detail01;
 
public class Cat extends Animal{
    public void eat(){//方法重写
        System.out.println("猫吃鱼");
    }
    public void catchMouse(){//Cat 特有方法
        System.out.println("猫抓老鼠");
    }
}
 
 
package Detail01;
 
public class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃骨头");
    }
}
 
package Detail01;
 
public class Polydetail {
    public static void main(String[] args) {
 
        Animal animal = new Cat();
        Object obj = new Cat();//Object 也是 Cat 的父类
 
//animal.catchMouse();错误
 
        animal.eat();//猫吃鱼.. animal.run();//跑
        animal.show();//hello,你好
        animal.sleep();//睡
 
        Cat cat = (Cat) animal;
        cat.catchMouse();//猫抓老鼠
 
//        Dog dog = (Dog) animal; //可以吗?
//        dog.eat();//错误的,因为现在animal指向cat的内存,
                    //如果我们要执行上面的那条语句,
                    //就相当于与把cat转成dao,这显然是错误
        System.out.println("ok~~");
    }
}
 

5.instanceof比较操作符

用于判断断对象的类型是否为 XX 类型或 XX 类型的子类型(是运行类型还是编译类型呢?)

看看下面代码输出结果时T还是F

class AA{}
class BB extends AA{}
 
 
BB bb = new BB();
System.out.println(bb instanceof BB);// true
System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
//BB 是 AA 子类
 
 
AA aa = new BB();
System.out.println(aa instanceof AA);
System.out.println(aa instanceof BB);//由此看出是看运行类型
 
 
Object obj = new Object();
System.out.println(obj instanceof AA);//false
String str = "hello";
//System.out.println(str instanceof AA);
System.out.println(str instanceof Object);//true

6.动态绑定机制

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

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

看看下面代码的输出结果

package Detail02;
 
public class DynamicBinding_ {
    public static void main(String[] args) {
//a 的编译类型 A, 运行类型 B
        A a = new B();//向上转型
        System.out.println(a.sum());//?40 -> 30
        System.out.println(a.sum1());//?30-> 20
    }
}
 
class A {//父类
    public int i = 10;
    //动态绑定机制:
    public int sum() {//父类 sum()
        return getI() + 10;//20 + 10
    }
    public int sum1() {//父类 sum1()
        return i + 10;//10 + 10
    }
    public int getI() {//父类 getI
        return i;
    }
}
class B extends A {//子类
    public int i = 20;
    // public int sum() {
    // return i + 20;
    // }
    public int getI() {//子类 getI()
        return i;
    }
    // public int sum1() {
    // return i + 10;
    // }
}

7.多态数组的应用

1)多态数组

package Polyarr;
 
public class Person {
    private String name;
    private int age;
 
    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }
 
    public String say(){
        return name + " " + age;
    }
}
 
 
package Polyarr;
 
public class Student extends Person{
    private double score;
 
    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }
 
    public double getScore() {
        return score;
    }
 
    public void setScore(double score) {
        this.score = score;
    }
 
    public String say(){
        return super.say() + " " + score;
    }
}
 
 
package Polyarr;
 
public class Teacher extends Person{
    private double salary;
 
    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }
 
    public double getSalary() {
        return salary;
    }
 
    public void setSalary(double salary) {
        this.salary = salary;
    }
 
    public String say(){
        return super.say() + " " + salary;
    }
}
 
 
package Polyarr;
 
public class arr_ {
    public static void main(String[] args) {
 
        Person[] persons = new Person[5];
        persons[0] = new Person("jack",20);
        persons[1] = new Student("jack",18,100);
        persons[2] = new Student("jack",19,10);
        persons[3] = new Teacher("king",21,200);
        persons[4] = new Teacher("sa",12,2000);
 
        for (int i = 0; i < 5; i++) {
            System.out.println(persons[i].say());
        }
    }
}

2)多态参数

package Polyparamaeter;
 
public class Employee {
 
    private String name;
    private double salary;
 
    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public double getSalary() {
        return salary;
    }
 
    public void setSalary(double salary) {
        this.salary = salary;
    }
 
    public double getAnnual(){
        return 12 * salary;
    }
}
 
 
package Polyparamaeter;
 
public class Manager extends Employee{
    private double bonus;
 
    public Manager(String name, double salary, double bonus) {
        super(name, salary);
        this.bonus = bonus;
    }
 
    public double getBonus() {
        return bonus;
    }
 
    public void setBonus(double bonus) {
        this.bonus = bonus;
    }
 
    public void manage(){
        System.out.println(getName() + "管理");
    }
 
    @Override
    public double getAnnual() {
        return super.getAnnual() + bonus;
    }
}
 
 
 
package Polyparamaeter;
 
public class Worker extends Employee{
    public Worker(String name, double salary) {
        super(name, salary);
    }
 
    public void work(){
        System.out.println(getName() + "工作");
    }
 
    @Override
    public double getAnnual() {
        return super.getAnnual();
    }
}
 
 
 
package Polyparamaeter;
 
public class Test {
    public static void main(String[] args) {
        Worker tom = new Worker("tom", 2500);
        Manager jack = new Manager("jack", 5000, 200000);
        Test test = new Test();
        test.showEmpAnnual(tom);
        test.showEmpAnnual(jack);
 
        test.testwork(tom);
    }
 
    public void showEmpAnnual(Employee e){
        System.out.println(e.getAnnual());//动态绑定机制
    }
 
    public void testwork(Employee e){
        if (e instanceof Worker){
            ((Worker) e).work();//向下转型
        }else if (e instanceof Manager){
            ((Manager) e).manage();//向下转型
        }else {
            System.out.println("no");
        }
    }
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值