zoukankan      html  css  js  c++  java
  • Java基础之面向对象

    1.面向对象

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

    封装

    1.方法就是一种封装

    2.关键字private也是一种封装

    封装就是将一些细节信息隐藏起来,对于外界不可见

    package com.dcits.day05.demo03;
    ​
    public class Demo02Method {
        public static void main(String[] args) {
            int[] array = {5,15,25,35,111};
            int max = getMax(array);
            System.out.println(max);
    ​
        }
        public static int getMax(int[] array) {
            int max = array[0];
            for (int i = 0; i < array.length; i++) {
                if (array[i] > max) {
                    max = array[i];
                }
            }
            return max;
        }
    }

    private关键字的作用以及使用

    一旦使用了private进行修饰,那么本类中可以随意访问,但是超出了本类的范围就不能再访问了

    可以通过间接访问的方式,自定义一对儿Getter/Setter方法,必须叫 setXxx 或者是 getXxx

    对于Getter来说,不能有参数,返回值类型和成员变量对应

    对于Setter来说,不能有返回值,参数类型和成员变量对应

    // Person类
    package com.dcits.day05.demo03;
    ​
    public class Person {
        String name;
        private int age;
        public void show() {
            System.out.println("我叫:" + name  +",今年" + age);
        }
        public void setAge(int num) {
            if (num < 100 && num >=9) {
                age = num;
            } else {
                age = 0;
                System.out.println("数据不合理");
            }
        }
        public int getAge() {
            return age;
        }
    }
    ​
    // 调用
    package com.dcits.day05.demo03;
    ​
    public class Demo03Person {
        public static void main(String[] args) {
            Person person = new Person();
            person.name = "赵丽颖";
    //        person.age = 18; 当成员变量被private修饰的时候,外部无法访问,只能通过间接的方式Setter,Getter
            person.setAge(-20);
            person.show();
        }
    ​
    }
     

    布尔类型的特殊情况

    //
    package com.dcits.day05.demo03;
    ​
    public class Student {
        private String name;
        private int age;
        private boolean male;
    ​
        public void setMale(boolean b){
            male = b;
        }
        public boolean isMale() {
            return male;
        }
    ​
        public void setName(String str){
            name = str;
        }
        public String getName() {
            return name;
        }
        public void setAge(int num) {
            age  = num;
        }
        public int getAge() {
            return age;
        }
    }
    // 调用
    package com.dcits.day05.demo03;
    ​
    public class Demo04Student {
        public static void main(String[] args) {
            Student stu = new Student();
            stu.setName("alex");
            stu.setAge(10);
            stu.setMale(true);
    ​
            System.out.println(stu.getName());
            System.out.println(stu.getAge());
            System.out.println(stu.isMale());
        }
    }
    ​

    this关键字的使用

    当方法的局部变量和类的成员变量重名的时候,根据就近原则,优先使用局部变量,如果需要访问 本类当中的成员变量,需要使用格式:this.成员变量

    通过谁调用的方法,谁就是this

    //
    package com.dcits.day05.demo04;
    ​
    public class Person {
        String name;
        public void sayHi(String name) {
            System.out.println(this.name + "你好,我是" + name);
        }
    }
    // 调用
    package com.dcits.day05.demo04;
    ​
    public class Demo01Person {
        public static void main(String[] args) {
            Person person = new Person();
            person.name = "6666";
            person.sayHi("777");
        }
    }

    构造方法

    构造方法是专门用来创建对象的方法,当我们使用关键字new来创建对象的时候,其实就是在调用构造方法

    注意事项:

    • 构造方法的名称必须和所在的类名称完全一样,就连大小写也要完全一样

    • 构造方法不要写返回值类型,连void都不要写

    • 构造方法不能return一个具体的返回值

    • 如果没有编写任何构造方法,那么编译器默认会赠送一个构造方法,没有参数、方法体什么都不做

    • 一旦编写了一个构造方法,那么编译器就不再赠送

    • 构造 方法也是可以重载的

    //
    package com.dcits.day05.demo04;
    ​
    public class Student {
        private String name;
        private int age;
        public Student(String name,int age) {
            this.name = name;
            this.age = age;
            System.out.println("有参数的构造方法!!");
        }
        public Student() {
            System.out.println("无参数的构造方法执行啦!!");
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public void setAge(int age) {
            this.age = age;
    ​
        }
        public int getAge() {
            return age;
        }
    }
    // 调用
    package com.dcits.day05.demo04;
    ​
    public class Demo02Student {
        public static void main(String[] args) {
            Student stu = new Student();
            Student stu1 = new Student("aaa",20);
            stu1.setAge(23);
            System.out.println(stu1.getAge());
            System.out.println(stu1.getName());
    ​
        }
    ​
    }
    ​

    局部变量和成员变量

    1. 定义的位置不一样

      • 局部变量:在方法的内部

      • 成员变量:在方法的外部,直接写在类当中

    2. 作用范围不一样

      • 局部变量:只有方法 才可以使用,出了方法就不能再使用了

      • 成员变量:整个类都可以通用

    3. 默认值不一样

      • 局部变量:没有默认值,如果想要用,必须手动赋值

      • 成员变量:如果没有赋值,会有默认值,规则和数组一样

    4. 内存的位置不一样

      • 局部变量:位于栈内存

      • 成员变量:位于堆内存

    5. 生命周期不一样

      • 局部变量:随着方法进栈而诞生,随着方法出栈而消失

      • 成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失

    标准类的组成部分

    一个标准的类通常拥有下面的四个部分:

    1. 所有的成员变量都要使用private关键字来修饰

    2. 为每一个成员变量编写一对Getter、Setter方法

    3. 编写一个无参数的构造方法

    4. 编写一个全参数的构造方法

    继承

    继承是多态的前提,如果没有集成,就没有多态

    继承解决的主要问题就是:共性抽取

    定义类时的两个注意事项:

    • 成员变量时直接定义在类当中的,在方法外面

    • 成员方法不要写static关键字

    继承的格式:

    // 父类
    package com.dcits.day08.demo01;
    ​
    public class Employee {
        public void method() {
            System.out.println("父类执行!");
        }
    }
    // Teacher子类
    package com.dcits.day08.demo01
    ​
    public class Teacher extends Employee{
    ​
    }
    // Assistant子类
    package com.dcits.day08.demo01;
    ​
    public class Assistant extends Employee {
    }
    // 调用
    package com.dcits.day08.demo01;
    ​
    public class Demo01Extends {
        public static void main(String[] args) {
            Teacher teacher = new Teacher();
            Assistant assistant = new Assistant();
            teacher.method();
            assistant.method();
        }
    }
     

    在父子类的继承关系当中,如果成员变量重名,则创建子类时,访问有两种方式:

    • 直接通过子类对象访问成员变量

      • 等号左边是谁,就优先使用谁,没有则向上找

    • 间接通过成员方法访问成员变量

      • 该方法属于谁,就优先用谁,没有则向上找

    // 父类
    package com.dcits.day08.demo02;
    ​
    public class Fu {
        int numFu = 10;
        int num = 100;
        public void methodFu() {
            System.out.println(num);
        }
    }
    ​
    // 子类
    package com.dcits.day08.demo02;
    ​
    public class Zi extends Fu {
        int numZi = 20;
        int num = 200;
        public void methodZi() {
            System.out.println(num);
        }
    }
    ​
    // 调用
    package com.dcits.day08.demo02;
    ​
    public class Demo01ExtendsField {
        public static void main(String[] args) {
            Fu fu = new Fu();
            System.out.println(fu.numFu);
    ​
            Zi zi =  new Zi();
            System.out.println(zi.numFu);
            System.out.println(zi.numZi);
    ​
            // 当父类与子类的成员变量重名的时候
            System.out.println(zi.num);
    //        System.out.println(zi.abc);
            //
            zi.methodZi();
            zi.methodFu();
        }
    ​
    ​
    }

     

    区分子类方法中的三种重名变量

    • 直接使用的方法中的变量

    • this.变量名:调用本类中的成员变量

    • super.变量名:调用父类中的成员变量

    // 父类
    package com.dcits.day08.demo03;
    ​
    public class Fu {
        int num = 10;
    }
    // 子类
    package com.dcits.day08.demo03;
    ​
    public class Zi extends Fu {
        int num = 20;
        public void method() {
            int num = 30;
            System.out.println(num); // 30 局部变量
            System.out.println(this.num); // 20 本类的成员变量
            System.out.println(super.num); // 10 父类的成员变量
        }
    }
    // 调用
    package com.dcits.day08.demo03;
    ​
    public class Demo01ExtendsField {
        public static void main(String[] args) {
            Zi zi = new Zi();
            zi.method();
        }
    }
    ​

    继承中成员方法的访问特点

    在父子类的继承关系当中,创建子类对象,访问成员方法的规则:创建的对象是谁,就优先使用谁,如果没有则向上找

    注意:无论是成员方法还是成员变量,如果没有都是向上找父类u,绝不会向下找子类

    // 父类
    package com.dcits.day08.demo04;
    ​
    public class Fu {
    ​
        public void methodFu() {
            System.out.println("父类中的方法执行啦!");
        }
    ​
        public void method() {
            System.out.println("父类重名执行啦!");
        }
    }
    ​
    // 子类
    package com.dcits.day08.demo04;
    ​
    public class Zi extends Fu {
        public void methodZi() {
            System.out.println("子类中的方法执行啦!");
        }
        public void method() {
            System.out.println("子类重名执行啦!");
        }
    }
    ​
    // 调用
    package com.dcits.day08.demo04;
    ​
    public class Zi extends Fu {
        public void methodZi() {
            System.out.println("子类中的方法执行啦!");
        }
        public void method() {
            System.out.println("子类重名执行啦!");
        }
    }
     

    继承方法中的覆盖重写

    重写:方法的名称一样,参数列表也一样,覆盖、覆写

    重载:方法的名称一样,参数列表不一样

    方法的覆盖重写特点:创建的是子类对象,则优先用子类方法

    方法覆盖重写的注意事项:

    1. 必须保证父子类之间的方法名称相同、参数列表也相同

    2. @Override:写在方法前面,用来检测是不是有效的正确覆盖重写,这个注释就算不写,只要满足要求,也是正确的覆盖重写

    3. 子类方法的返回值必须小于等于父类方法的返回值范围。Object类是所有类的父类

    4. 子类方法的权限必须大于等于父类方法的权限修饰符。public > protected > (default) > private 注意:(default)不是关键字default,而是什么都不写,留空

    继承中方法的覆盖重写应用场景

    // 父类
    package com.dcits.day08.demo06;
    // 本来的老款手机
    public class Phone {
        public void   call() {
            System.out.println("打电话");
        }
    ​
        public void send() {
            System.out.println("发短信");
        }
    ​
        public void show() {
            System.out.println("显示号码");
        }
    }
    ​
    // 子类
    package com.dcits.day08.demo06;
    // 上市的新款手机
    public class NewPhone extends Phone {
        @Override
        public void show() {
    //        System.out.println("显示号码");
            super.show();
            System.out.println("显示姓名");
            System.out.println("显示头像");
        }
    }
    ​
    // 调用
    package com.dcits.day08.demo06;
    ​
    public class Demo01Phone {
        public static void main(String[] args) {
            Phone phone = new Phone();
            phone.call();
            phone.send();
            phone.show();
            System.out.println("===========");
    ​
            NewPhone newPhone = new NewPhone();
    ​
            newPhone.call();
            newPhone.send();
            newPhone.show();
        }
    }

     

    继承中构造方法的访问特点

    1. 子类构造方法当中有一个默认隐含的 "super()" 调用,所以一定是先调用的父类构造,后执行的子类构造

    2. 子类构造可以通过super关键字来调用父类重载构造

    3. super的父类构造调用,只能是第一个语句 ,不能一个子类构造调用多次super构造

    4. 子类必须调用父类构造方法,不写赠送super() 写了则用写的指定该的super调用,super只能有一个,还必须是第一个

    super关键字的用法(访问父类的内容):

    1. 在子类的成员方法中,访问父类的成员变量

    2. 在子类的成员方法中,访问父类的成员方法

    3. 在子类的构造方法中,访问父类的构造方法

    // 父类
    package com.dcits.day08.demo08;
    ​
    public class Fu {
        int num = 10;
        public void method(){
            System.out.println("父类方法");
        }
    }
    ​
    // 子类
    package com.dcits.day08.demo08;
    ​
    public class Zi extends Fu {
        int num = 20;
        public Zi(){
            super();
        }
        public void methodZi() {
            System.out.println(super.num); // 父类的num
        }
        public void method(){
            super.method();
            System.out.println("子类方法");
        }
    }
    ​

    this关键字的三种使用方法(访问本类的内容)

    1. 在本类的成员方法中,访问本类的成员变量

    2. 在本类的成员方法中访问本类的另一个成员方法

    3. 在本类的构造方法中,访问本类的另一个构造方法

    注意:

    • 在第三种用法中要注意:this(..)调用必须是构造方法的一个语句,唯一一个

    • super和this两种构造调用,不能同时使用

    // 父类
    package com.dcits.day08.demo09;
    ​
    public class Fu {
        int num = 30;
    }
    // 子类
    package com.dcits.day08.demo09;
    ​
    public class Zi extends Fu {
        int num = 20;
        public Zi(){
            this(123); // 本类的无参构造,调用本类的有参构造
    //        this(1,2)
        }
        public Zi(int n){
    ​
        }
        public Zi(int n,int m){
    ​
        }
        public void showNum(){
            int num = 10;
            System.out.println(num);
            System.out.println(this.num); // 本类中的成员变量
            System.out.println(super.num); // 父类中的 成员变量
        }
        public void methodA() {
            System.out.println("AAA");
        }
        public void methodB() {
            methodA();
            this.methodA();
            System.out.println("BBB");
        }
    }

    this、super的关键字图解

    Java语言继承的三个特点:

    • 一个类的 直接父类只能有唯一一个

    • Java语言可以多继承

    • 一个子类的直接父类是唯一的,但是一个父类可以拥有很多个子类

     

    多态

    多态的定义以及基本使用

    extends继承或者implements实现,是多态的前提。

    小明这个对象既有学生形态,也有人类形态。一个对象拥有多种形态,这就是:对象的多态性

    代码当中体现多态性,其实就是一句话:父类引用指向子类对象

    格式:

    • 父类名称 对象名 = new 子类名称()

    • 接口名称 对象名 = new 实现类名称()

    // 父类
    package com.dcits.day09.demo04;
    ​
    public class Fu {
        public void method(){
            System.out.println("父类方法");
        }
        public void methodFu(){
            System.out.println("父类特有方法");
        }
    }
    // 子类
    package com.dcits.day09.demo04;
    ​
    public class Zi extends Fu {
        @Override
        public void method() {
            System.out.println("子类方法");
        }
    }
    // 调用
    package com.dcits.day09.demo04;
    ​
    ​
    ​
    public class Demo01Multi {
        public static void main(String[] args) {
            // 使用多态的写法
            // 左侧父类的引用指向右侧子类的对象
            Fu obj = new Zi();
            // new 的是谁就调用谁 的方法
            obj.method(); // 子类方法
            obj.methodFu(); // 父类特有方法
        }
    }
    ​

    多态中成员变量的使用特点

    访问成员变量的两种方式:

    1. 直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找

    2. 间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则像上找

    // 父类
    package com.dcits.day09.demo05;
    ​
    public class Fu {
        int num = 10;
    ​
        public void showNum(){
            System.out.println(num);
        }
    }
    // 子类
    package com.dcits.day09.demo05;
    ​
    public class Zi extends Fu {
        int num = 20;
    ​
        int age = 16;
    ​
        @Override
        public void showNum() {
            System.out.println(num);
        }
    }
    // 调用
    package com.dcits.day09.demo05;
    ​
    public class Demo01MultiField {
        public static void main(String[] args) {
           Fu obj = new Zi();
            System.out.println(obj.num); // 父类中的10
            System.out.println("=====================");
            obj.showNum(); // 子类没有覆盖重写,就是父类中的num,一旦子类重写后就是子类中的num
        }
    }
    ​

    多态中成员方法的使用特点

    在多态的代码当中,成员方法的优先访问规则是:看new的是谁,就优先用谁,没有则向上找

    注意:编译看左边,运行看右边

    对比一下:

    • 成员变量:编译看左边,运行还看左边

    • 成员方法:编译看左边,运行看右边

    // 父类
    package com.dcits.day09.demo05;
    ​
    public class Fu {
        int num = 10;
    ​
        public void showNum(){
            System.out.println(num);
        }
    ​
        public void method(){
            System.out.println("父类方法");
        }
        public void methodFu(){
            System.out.println("父类特有方法");
        }
    }
    // 子类
    package com.dcits.day09.demo05;
    ​
    public class Zi extends Fu {
        int num = 20;
    ​
        int age = 16;
    ​
        @Override
        public void showNum() {
            System.out.println(num);
        }
    ​
        @Override
        public void method() {
            System.out.println("子类方法");
        }
        public void methodZi(){
            System.out.println("子类特有方法");
        }
    }
    ​
    // 调用
    package com.dcits.day09.demo05;
    ​
    public class Demo01MultiField {
        public static void main(String[] args) {
           Fu obj = new Zi();
           obj.method(); // 父子都有,优先使用子类
           obj.methodFu(); // 子类没有,父类有,向上找到父类
            // 编译看左,左边是Fu,没有methodZi方法,所以编译报错
    //        obj.methodZi(); // 错误写法
    //        System.out.println(obj.num); // 父类中的10
    //        System.out.println("=====================");
    //        obj.showNum(); // 子类没有覆盖重写,就是父类中的num,一旦子类重写后就是子类中的num
        }
    }
    ​

    使用多态的好处

    对象的向上转型

    对象的向上转型,其实就是多态写法

    格式: 父类名称 对象名 = new 子类名称()

    含义:右侧创建一个子类对象,把它当作父类来看待使用

    注意事项:

    • 向上转型一定是安全的,从小范围转到了大范围

    • 但是有一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本的特有内容

    类似于:double num = 100 正确 int----double 自动类型转换

    // 父类
    package com.dcits.day09.demo06;
    ​
    public abstract class Animal {
        public abstract void eat();
    }
    // 子类
    package com.dcits.day09.demo06;
    ​
    public class Cat extends Animal {
        @Override
        public void eat() {
            System.out.println("猫吃鱼。。。");
        }
    }
    ​
    // 调用
    package com.dcits.day09.demo06;
    ​
    public class Demo01Main {
        public static void main(String[] args) {
            Animal animal = new Cat();
            animal.eat();
        }
    ​
    }

    对象的向下转型

    对象的向下转型,其实是一个还原动作

    格式:子类名称 对象名 = (子类名称) 父类对象

    含义:将父类对象,还原成为原本的子类对象

    注意事项:

    • 必须保证对象本来创建的时候,就是猫,才能向下转型成为猫

    • 如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错

    类似于:int num = (int) 10.0 正确 int num = (int) 10.5 错误,发生精度损失

    // 父类
    package com.dcits.day09.demo06;
    ​
    public abstract class Animal {
        public abstract void eat();
    }
    // 猫子类
    package com.dcits.day09.demo06;
    ​
    public class Cat extends Animal {
        @Override
        public void eat() {
            System.out.println("猫吃鱼。。。");
        }
    ​
        public void catchMouse() {
            System.out.println("猫抓老鼠!!");
        }
    }
    ​
    // 狗子类
    package com.dcits.day09.demo06;
    ​
    public class Dog extends Animal {
        @Override
        public void eat() {
            System.out.println("狗吃shit");
        }
    ​
        public void watchMouse() {
            System.out.println("狗看家!!");
        }
    }
    ​
    // 调用
    package com.dcits.day09.demo06;
    ​
    public class Demo01Main {
        public static void main(String[] args) {
    ​
            Animal animal = new Cat(); // 对象的向上转型
            animal.eat();
    ​
            // 向下转型
            Cat cat = (Cat) animal;
            cat.catchMouse(); // 猫抓老鼠!!
    // 下面是错误的向下转型
            // 本来new的时候是一只猫,现在非要转成狗
            // java.lang.ClassCastException
            Dog dog = (Dog) animal; // 错误写法
    ​
        }
    ​
    }
    ​

    用instanceof 关键字进行类型判断

    package com.dcits.day09.demo06;
    ​
    public class Demo01Instanceof {
        public static void main(String[] args) {
            Animal animal = new Cat(); // 本来是一只猫
            animal.eat();
    ​
            // 如果需要调用子类特有的方法,需要向下转型
            if (animal instanceof Dog){
                Dog dog = (Dog) animal;
                dog.watchMouse();
            }
            if (animal instanceof Cat){
                Cat cat = (Cat) animal;
                cat.catchMouse();
            }
            giveMeAPet(new Dog()); // 在你调用这个方法的时候,方法本身不知道传递过来的是哪个类,所以需要进行判断
    ​
        }
    ​
        public static void giveMeAPet(Animal animal){
            if (animal instanceof Dog){
                Dog dog = (Dog) animal;
                dog.watchMouse();
            }
            if (animal instanceof Cat){
                Cat cat = (Cat) animal;
                cat.catchMouse();
            }
    ​
        }
    }

    接口多态的综合案例

    // USB接口类:两个抽象方法:打开USB、关闭USB
    package com.dcits.day09.demo07;
    ​
    public interface USB {
    ​
        public abstract void open();
    ​
        public abstract void close();
    }
    ​
    // 电脑类:开机、关机、连接USB接口并对USB设备进行对应操作
    package com.dcits.day09.demo07;
    ​
    public class Computer {
        public void powerOn(){
            System.out.println("笔记本电脑开机");
        }
    ​
        public void powerOff(){
            System.out.println("笔记本电脑关机");
        }
    ​
        // 使用USB设备的方法,使用接口作为方法的参数
        public void useDevice(USB usb) {
            usb.open();
            // 判断当前类是属于哪个类之后,在获取类中的特有方法
            if (usb instanceof Mouse){
                Mouse mouse = (Mouse) usb;
                mouse.click();
            } else if (usb instanceof KeyBoard){
                KeyBoard keyboard = (KeyBoard) usb;
                keyboard.type();
            }
            usb.close();
        }
    }
    ​
    // 鼠标类:重写接口类中的打开、关闭功能,并实现自己的独有功能
    package com.dcits.day09.demo07;
    ​
    public class Mouse implements USB {
        @Override
        public void open() {
            System.out.println("打开鼠标");
        }
    ​
        @Override
        public void close() {
            System.out.println("关闭鼠标");
        }
    ​
        public void click(){
            System.out.println("点击鼠标!");
        }
    }
    ​
    // 键盘类:重写接口类中的打开、关闭功能,并实现自己的独有功能
    package com.dcits.day09.demo07;
    ​
    public class KeyBoard implements USB {
        @Override
        public void open() {
            System.out.println("打开键盘");
        }
    ​
        @Override
        public void close() {
            System.out.println("关闭键盘");
        }
    ​
        public void type(){
            System.out.println("敲键盘!");
        }
    }
  • 相关阅读:
    shutil、zipfile,tarfile
    time、datetime、calendar
    stat
    os与sys模块
    数据同步解决方案
    Oracle数据同步交换
    SQL Server数据同步交换
    MySQL数据同步交换
    Informix网页数据维护客户端工具
    Kingbase数据库web统一管理平台
  • 原文地址:https://www.cnblogs.com/guoruijie/p/13294921.html
Copyright © 2011-2022 走看看