JavaSE| 面向对象的三大特征

Posted kris12

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE| 面向对象的三大特征相关的知识,希望对你有一定的参考价值。

 

 面向对象的基本特征之一:封装Encapsulation

目的:隐藏实现细节,让使用者方便,让代码更安全

 将对象的属性和行为封装起来,其载体就是类。类通常对客户隐藏其实现细节,这就是封装的思想。

封装(Encapsulation):把该隐藏的隐藏起来,该暴露的暴露出来。

封装需要通过访问控制修饰符(权限修饰符)来实现。

/*
权限修饰符:
                本类    其他类(本包的其他类、其他包的子类、其他包的非子类)
private            √                   ×         ×            ×   (只适用于本类中)
缺省(省略)       √                   √         ×            ×  (使用与本包中)
protected(受保护的)√                   √         √            ×   (本类 + 本包其他类 + 其他包的子类 )
public             √                   √         √            √

权限修饰符的作用:限定某个类型、成员的可访问的范围、可见性的范围

权限修饰符可以修饰什么?
private:成员(属性、方法、构造器、内部类)
缺省:外部类等类型、成员(属性、方法、构造器、内部类)
protected:成员(属性、方法、构造器、内部类)
public:外部类等类型、成员(属性、方法、构造器、内部类)
    当public修饰外部类时,要注意类名必须与源文件名一致,即一个源文件只能有一个外部的public类

修饰符的学习:(1)可以修饰什么(2)修饰后有什么影响
*/
//外部类
public class TestModifier{
    //内部类
    public class Inner{
        
    }
}

 

面向对象的基本特征之二:继承

* 继承:延续,保留,并且扩展 extends
* 目的:代码的复用和功能扩展; 继承还可以表示is-a的逻辑关系;Student is a Person.   Apple is a Fruit.

* 2、如何继承?
* 【修饰符】 class 子类名 extends 父类名{
* }
*
* 子类:SubClass,也称为派生类;     父类:SuperClass,也称为超类、基类

* 3、继承的特点
* (1)子类继承父类时,会继承父类的所有的属性、方法。* 但是因为修饰符的原因,某些属性和方法在子类中不可见。
* (2)子类“不会”继承父类的构造器;
* (3)在子类的构造器中一定会“调用”父类的构造器,并且默认调用的是父类的“无参”构造器

    如果父类没有“无参”构造,那么子类必须手动调用父类的“有参”构造。(子类在创建对象时候默认调用父类的无参构造器)
* (4)如果一个类没有显式的声明它的父类,那么它有一个默认的父类:java.lang.Object
* (5)在Java中,类的继承有“单继承限制”;意思:每一个子类只能有一个直接的父类,类似于每个人只有一个亲生父亲
* (6)Java中支持多层继承,即父类仍然可以有父类,子类会继承所有父类的属性和方法。 意思:代代相传
* (7)一个父类却同时可以有很多的子类,而且子类还可以有很多子类;* 意思:子孙满堂
* (8)子类可以扩展父类没有的属性和方法

 

* this关键字:当前对象
 * (1)this.属性
 * 当成员变量与局部变量重名时,在成员变量前面加"this."
 * 
 * (2)this.方法
 * 表示调用当前对象的成员方法,可以省略this.
 * 
 * (3)this()或this(实参列表)
 * this()或this(实参列表)调用本类的无参构造
 * 
 * super关键字:父类的  
 * 前提:要通过super调用父类的属性、方法、构造器,必须要求他们的可见性是在子类中可见的。
 * 
 * (1)super.属性
 *子类的属性与父类的属性重名时,可以使用super.属性 表示父类的属性。
 * 
 * (2)super.方法
 * 当子类重写了父类的方法,又想调用父类被重写的方法,那么可以使用“super.父类的方法名 被重写方法”
 * 
 * (3)super()或super(实参列表)
 * super()表示调用父类的无参构造器,可以省略,
 * super(实参列表)表示调用父类的有参构造,不可以省略,特别是父类没有无参构造时
 * 要求:和this()、this(实参列表)一样,必须在构造器的首行。
    public Manager() {
        super();
    }

    public Manager(String name, double salary, double bonus) {
        super(name, salary);   //调用父类的有参构造   加上   子类自己扩展的属性。
        this.bonus = bonus;
    }

    if(amount < balance){
            //正常取
        super.withdraw(amount); //调用父类的withdraw方法;方法的重写。

面向对象的基本特征之三:多态

多种形态,目的是使代码更灵活,功能更丰富。

 * 如何理解它? 针对方法
 * 1、方法的重载与重写:一个功能有多种形式
 * public static int getMax(int x, int y)
 * public static int getMax(int x, int y,int z)
 * public static double getMax(double x, double z)
 * 功能都是找最大值,它有多种形式
 * 
 * public class Employee{
 *     public String getInfo(){
 *         ....
 *     }
 * }
 * public class Manager extends Employee{
 *     public String getInfo(){
 *         .... + 奖金
 *     }
 * }
 * 父子类中该方法都是返回对象的详细信息,但是父子类中有两种形式
 * 
 * 2、对象的多态性
 *     某个对象在Java中可能出现 1)编译时类型; 2)运行时类型,不一致
 *                       编辑代码并且javac      java
 *  前提条件:
 *  (1)类有继承关系
 *  (2方法的重写
 *  (3)多态引用:父类的变量指向子类的对象
 *  Person p = new Man();
 *  出现的对象多态性的现象:
 *      编译时按照父类的类型编译,运行时按照子类的类型运行,执行的方法是子类重写的方法体。
 * 
 */

 

public class TestPolymorphism {
    public static void main(String[] args) {
//        Object obj = new String("hello");
//        此时的obj对象就有两种类型,编译时类型是Object类型,运行时是String类型
    }
}
//本态引用:编译时类型和运行时类型是一样的
//        Person p = new Person(); 
//        Man m = new Man();
//        Girl g = new Girl();
Person p = new Man(); //编译时类型是Person,运行时类型是Man
        p.eat();  //运行时候是Man类型; 
        p.smoke();//编译时报错,因为p在编译时按照Person类型,Person类型中没有smoke()方法


class Person{
public void eat(){
System.out.println("吃吃吃饭");
}
public void sleep(){
System.out.println("睡觉觉");
}

}

class Man extends Person{//难人
public void eat(){
System.out.println("狼吞虎咽");
}
public void sleep(){
System.out.println("呼呼大睡");
}
public void smoke(){
System.out.println("吞云吐雾");
}
}

 

* 多态的第一个应用:多态数组
 * 元素的类型是父类的类型,元素存的是子类的对象
 * 
 * 需求:用一个数组来存储多个图形对象,这里面可能有圆对象,可能有矩形对象,统一管理他们,要显示他们的面积、周长、向下信息等,甚至按照面积排序...
 * 1、声明一个Circle类,有半径radius,有求面积的方法,求周长的方法,返回详细信息的方法
 * 2、声明一个Rectangle矩形类,有长和宽,有求面积的方法,求周长的方法,返回详细信息的方法
 * 3、声明一个父类Graphic图形类,让Circle和Rectangle继承它
 * 
 * 类:一类具有相同特性的事物的抽象描述。

 

public class TestUse1 {

    public static void main(String[] args) {
        
        //多态引用,左边的arr[]是父类的类型Graphic,右边赋值的是子类的对象;
        Graphic[] arr = new Graphic[3]; //数组的声明和初始化
        arr[0] = new Circle(2);
        arr[1] = new Ractangle(3,2);
        arr[2] = new Circle(6.1);
        
        //编译时g按照Graphic的父类类型编译,执行的时候,执行的是子类重写的方法体
        for(Graphic num: arr){
            System.out.println(num.getInfo() + "
");
            //System.out.println(num.getArea() + "	");
        }

    }
}

 

技术分享图片
public class TestUse1 {

    public static void main(String[] args) {
        
        //多态引用,左边的arr[]是父类的类型Graphic,右边赋值的是子类的对象;
        Graphic[] arr = new Graphic[3]; //数组的声明和初始化
        arr[0] = new Circle(2);
        arr[1] = new Ractangle(3,2);
        arr[2] = new Circle(6.1);
        
        //编译时g按照Graphic的父类类型编译,执行的时候,执行的是子类重写的方法体
        for(Graphic num: arr){
            System.out.println(num.getInfo() + "
");
            //System.out.println(num.getArea() + "	");
        }

    }
}


package com.atguigu.variable;

public class Graphic {
    public double getArea(){
        return 0.0;
    }
    public double getPrimeter(){
        return 0.0;
    }
    public String getInfo(){
        return "";
    }
}


package com.atguigu.variable;

public class Circle extends Graphic{
    private double radius;

    public Circle() {
        super();
    }

    public Circle(double radius) {
        super();
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double getArea(){
        return Math.PI * radius * radius;
    }
    public double getPrimeter(){
        return 2 * Math.PI * radius;
    }
    public String getInfo(){
        return "半径" + radius + "	面积" + getArea() + "	周长" + getPrimeter(); 
    }
    
}


package com.atguigu.variable;

public class Ractangle extends Graphic{
    private double length;
    private double width;
    public Ractangle() {
        super();
    }
    public Ractangle(double length, double width) {
        super();
        this.length = length;
        this.width = width;
    }
    public double getLength() {
        return length;
    }
    public void setLength(double length) {
        this.length = length;
    }
    public double getWidth() {
        return width;
    }
    public void setWidth(double width) {
        this.width = width;
    }
    
    public double getArea(){
        return length * width;
    }
    public double getPrimeter(){
        return 2 * (length + width);
    }
    public String getInfo(){
        return "长" + length +"	宽:"+ width + "	面积" + getArea() + "	周长" + getPrimeter(); 
    }
}
View Code

 

* 多态的应用之二:多态参数
 * 形参是:父类类型
 * 实参是:子类的对象
 * 
 * 需求:
 * 1、声明一个Circle类,有半径radius,有求面积的方法
 * 2、声明一个Rectangle矩形类,有长和宽,有求面积的方法
 * 3、声明一个Triangle三角形,有三边,有求面积的方法
 * 3、在测试类中,声明一个方法,功能:可以比较任意两个图形对象的面积,是否相等
public class TestUse2 {

    public static void main(String[] args) {
        Circle c = new Circle(2);
        Ractangle r = new Ractangle(3, 2);
        //实参给形参赋值
        //形参的类型:Graphic,实参的类型:一个是Circle,一个是Rectangle
        //隐含了:Graphic g1 = c;//多态引用
        //隐含了:Graphic g2 = r;//多态引用
        boolean result = equalsGraphic(c, r);
        if(result){
            System.out.println("面积相等");
        }else{
            System.out.println("面积不相等");
        }

    }
    //可以比较任意两个图形对象的面积,是否相等
    //返回值类型:boolean
    //形参?两个图形类型
    public static boolean equalsGraphic(Graphic g1, Graphic g2){
        //g1和g2编译时按照Graphic类型,运行时g1按照Circle,g2按照Rectangle类型
        if(g1.getArea() == g2.getArea()){
            return true;
        }else{
            return false;
        }
    }
    
}

 

* 基本数据类型:byte,short,int,long,float,double,boolean,char
 * 1、自动类型转换
 * byte,short,char->int->long->float->double
 * boolean不参与
 * ....
 * 
 * 2、强制类型转换
 * double->float->long->int->char,byte,short
 * 强制类型转换需要(),可能损失精度或溢出
 * boolean不参与
 * ....
 * 
 * 父子类之间类型转换:
 * 1、向上转型:自动完成
 *     Person p = new Man();//一个Man的对象在编译期间向上转型为Person类型
 * 
 *  Graphic[] arr = new Graphic[5];
 *  arr[0] = new Circle(2);//一个Circle对象在编译期间向上转型为Graphic类型
 *  
 * 2、向下转型:强制完成
 *     Person[] arr = new Person[5];
    arr[0] = new Man();//向上转型
    Man m = (Man) arr[0];//向下转型
 *
 *    向下转型之前,一定发生过向上转型。
 *
 * 
 * 父类的变量中可以存储子类的对象,
 * 但是子类的变量中是不能存储父类的对象。
* 关键字:instanceof * 为了避免转型的失败,可以在转型之前加instancof判断

 

public class TestClassCast {

    public static void main(String[] args) {
        Person[] arr = new Person[3];
        arr[0] = new Man();
        arr[1] = new Girl();
        arr[2] = new Person();
        
        //希望调用Man类型的smoke()方法
        //arr[0].smoke(); //编译时,arr[0]是按照父类Person类型编译的
        Man m = (Man) arr[0]; //向下转型;
        m.smoke();
        
        //编译没保错,因为编译时,arr[1]按照父类Person类型编译的,从Person类型向下转为Man,语法上可以
        //Man m2 = (Man)arr[1];//运行时,发生java.lang.ClassCastException:类型转换异常
        //m2.smoke();           //.Girl cannot be cast to .Man
        
        Man m3 = (Man)arr[2];//运行时,发生java.lang.ClassCastException:类型转换异常
        m3.smoke();        //.Person cannot be cast to .Man 
    }

}

 

Man m  -->>指向Man对象是可以的

Man m2 --->>不能指向Girl对象,因为它俩之间没有继承关系的。

Man m3 ---->>不能指向Person父对象。

 

public class TestClassCast {

    public static void main(String[] args) {
        Person[] arr = new Person[3];
        arr[0] = new Man();
        arr[1] = new Girl();
        arr[2] = new Person();
        for(Person p : arr){
            p.eat();
            //p.sleep();
            if(p instanceof Man){
                Man m =(Man) p;
                m.smoke();
            }if(p instanceof Girl){
                Girl g = (Girl) p;
                g.shopping();
            }
        }
    }
}

 

以上是关于JavaSE| 面向对象的三大特征的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE基础之面向对象(上)

JavaSE(面向对象之类和类的成员)

JavaSE(面向对象)

JavaSE--面向对象

面向对象三大特征是啥?

“面向对象”的三大特征是啥,各自的定义是啥?