zoukankan      html  css  js  c++  java
  • 面向对象编程

    面向对象编程

    什么是面向对象

    面向对象思想

    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。

    • 面向对象适合处理复杂的问题适合处理需要多人协作的问题!

    • 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

    面向对象编程的本质就是

    以类的方式组织代码,以对象的形式封装数据

    面向对象的核心思想

    抽象

    三大特性

    • 封装
    • 继承
    • 多态

    认识论的角度:现有对象后有类。

    代码运行的角度:先有类后有对象。

    类和对象的关系

    • 类是一种抽象的数据类型,它是对某一类事物的整体描述,但是并不能代表某一个具体的事物。

    • 对象是抽象概念的具体实例

    创建与初始化对象

    • 使用new关键字创建对象

    • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。

    • 类中的构造器也叫做构造方法,是在进行创建对象的时候必须要调用的。并且构造方法有以下两个特点:

      1. 必须和类的名字相同
      2. 必须没有返回类型,也不能写void

    Application.java

    package com.oop.demo02;
    
    public class Application {
        public static void main(String[] args) {
            //类:抽象的,实例化
            //类实例化后会返回一个自己的对象!
            //student对象就是一个Student类的具体实例!
    
            Student ming = new Student();
            Student hong = new Student();
    
            ming.name = "小明";
            ming.age = 3;
    
            System.out.println(ming.name);
            System.out.println(ming.age);
    
    
            hong.name = "小红";
            hong.age = 3;
    
    
            System.out.println(hong.name);
            System.out.println(hong.age);
    
    
        }
    }
    

    Student.java

    package com.oop.demo02;
    
    public class Student {
        //属性:字段
        String name;
        int age;
    
        //方法
        public void study(){
            System.out.println(this.name+"在学习");
        }
    }
    

    构造器详解

    Application.java

    package com.oop.demo02;
    
    public class Application {
        public static void main(String[] args) {
            //new  实例化了一个对象
            Person person = new Person("xx",21);
    
            System.out.println(person.name);
    
    
        }
    }
    

    Person.java

    package com.oop.demo02;
    
    //java-->class
    public class Person {
    
        //一个类即使什么都不写,它也会存在一个方法
        //显式的定义构造器
    
        String name;
        int age;
    
        //实例化初始值
        //1.使用new关键字,本质是在调用构造器
        public Person(){
            this.name = "xx";
        }
    
        //有参构造:一旦定义了有参构造,无参就必须显示定义
        public Person(String name) {
            this.name = name;
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    

    快捷键alt + insert

    构造方法:

    1. 和类名相同
    2. 没有返回值

    作用:

    1. new本质在调用构造方法
    2. 初始化对象的值

    注意点:

    1. 定义有参构造之后,如果想使用无参构造,显式的定义一个无参的构造。

    创建对象内存分析

    Application.java

    package com.oop.demo02;
    
    public class Application {
        public static void main(String[] args) {
            Pet dog = new Pet();
    
            dog.name = "旺财";
            dog.age = 3;
            dog.shout();
    
            System.out.println(dog.name);
            System.out.println(dog.age);
    
            Pet cat = new Pet();
    
        }
    }
    

    Pet.java

    package com.oop.demo02;
    
    public class Pet {
        String name;
        int age;
    
        public void shout(){
            System.out.println("叫了一声");
        }
    }
    

    内存分析图image-20201121001941005

    小结

    1. 类与对象

      类是一个模板:抽象,对象是一个具体的实例

    2. 方法

      定义、调用

    3. 对象的引用

      引用类型:基本类型(8)

      对象是通过引用来操作的:栈-->堆

    4. 属性:字段Field 成员变量

      默认初始化:

      ​ 数字:0 0.0

      ​ char: u0000

      ​ boolean: false

      ​ 引用:null

      修饰符 属性类型 属性名 = 属性值

    5. 对象的创建和使用

      • 必须使用new关键字创造对象,构造器 Person xw = new Person();
      • 对象的属性 xw.name
      • 对象的方法 xw.sleep();
    6. 静态的属性

      动态的方法

    封装

    高内聚,低耦合

    • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
    • 低耦合:仅仅暴露少量的方法给外部使用

    封装(数据的隐藏)

    • 通常应该禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这叫做信息隐藏

    属性私有,get/set

    Student.java

    package com.oop.Demo04;
    
    public class Student {
    
        //属性私有
        private String name;//名字
        private int num;//学号
        private char sex;//性别
        private int age;
    
        //提供一些可以操作这个属性的方法——get/set
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if (age>120||age<0){
                this.age = 3;
            }else{
                this.age = age ;
            }
    
        }
    }
    

    Application.java

    package com.oop;
    import com.oop.Demo04.Student;
    
    public class Application {
        public static void main(String[] args) {
    
            Student s1 = new Student();
    
            s1.setName("xx");
            System.out.println(s1.getName());
            s1.setAge(100);
            System.out.println(s1.getAge());
        }
    }
    

    封装的好处

    1. 提高程序的安全性,保护数据
    2. 隐藏代码的实现细节
    3. 统一接口
    4. 系统可维护增加了

    继承

    • 继承的本质是对某一批类的抽象,从而实现对显示世界更好的建模
    • extends的意思是“扩展”。子类是父类的扩展。
    • Java只有单继承,没有多继承!
    • 继承是类与类之间的关系,除此之外还有组合,依赖,聚合...
    • 子父类之间,从意义上讲应该具有“is a”的关系。

    Person.java

    package com.oop.Demo05;
    
    public class Person {
    
        private int money = 1_9999;
    
        public void say(){
            System.out.println("说了一句话");
        }
    
        public void setMoney(int money){
            this.money = money;
        }
        public int getMoney() {
            return this.money;
        }
    }
    

    Application.java

    package com.oop;
    
    
    import com.oop.Demo05.Student;
    
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.say();
            student.setMoney(10009999);
            System.out.println(student.getMoney());
        }
    }
    

    Student.java

    package com.oop.Demo05;
    
    import java.util.Scanner;
    
    public class Student extends Person{
    
    }
    

    super详解

    Student.java

    package com.oop.Demo05;
    
    
    public class Student extends Person{
    
        public Student() {
            //默认调用了父类的无参构造
            super();//调用父类的构造器,必须要在子类构造器的第一行
            System.out.println("Student无参执行了");
        }
    
        private String name = "xx";
    
        public void print(){
            System.out.println("Student");
        }
    
        public void test1(){
            print();
            this.print();
            super.print();
        }
    
        public void test(String name){
            System.out.println(name);
            System.out.println(this.name);
            System.out.println(super.name);
        }
    }
    

    Person.java

    package com.oop.Demo05;
    
    public class Person {
    
        public Person() {
            System.out.println("Person无参执行了");
        }
    
        public Person(String name) {
            this.name = name;
        }
    
        protected String name = "kiku";
    
        public void print(){
            System.out.println("Person");
        }
    }
    

    Application.java

    package com.oop;
    
    import com.oop.Demo05.Person;
    import com.oop.Demo05.Student;
    
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
    //        student.test("xw");
    //        System.out.println("==================");
    //        student.test1();
        }
    }
    

    super注意点

    1. super调用父类的构造方法,必须在构造方法的第一个
    2. super必须只能出现在子类的方法或者构造方法
    3. super和this不能同时调用构造方法

    super vs this:

    代表的对象不同:

    ​ this:本身调用者这个对象

    ​ super:代表父类对象的引用

    前提

    ​ this:没继承也可以使用

    ​ super:只能在继承条件才可以使用

    构造方法

    ​ this():本类的构造

    ​ super():父类的构造

    方法重写

    B.java

    package com.oop.Demo06;
    
    public class B {
    
        public  void test(){
            System.out.println("B=>test()");
        }
    }
    

    A.java

    package com.oop.Demo06;
    
    public class A extends B {
        //@Override 重写
        @Override//注释:有功能的注释!
        public void test() {
            System.out.println("=>test()");
    
        }
    }
    

    Application.java

    package com.oop;
    
    
    import com.oop.Demo06.A;
    import com.oop.Demo06.B;
    
    public class Application {
    
        //静态方法和非静态方法区别很大
    
    
        //非静态;重写
        public static void main(String[] args) {
            //方法的调用只和左边,定义的数据类型有关
            A a = new A();
            a.test();
    
            //父类的引用指向了子类
            B b = new A();//子类重写了父类的方法
            b.test();
        }
    }
    

    重写:

    需要有继承关系,子类重写父类的方法!

    1. 方法名必须相同

    2. 参数列表必须相同

    3. 修饰符:范围可以扩大:

      public > protected > default > private

    4. 抛出的异常:范围可以被缩小,但不能扩大。

      ClassNotFoundException

    子类的方法和父类必要一致,方法体不同!

    为什么要重写:

    • 父类的功能,子类不一定需要,或者不一定满足。

    IDEA快捷键:alt + insert: @Override;

    多态

    动态编译,类型:可扩展

    同一方法可以根据发送对象的不同而采用多种不同的行为方式

    一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多

    多态存在的条件

    • 有继承关系
    • 子类重写父类的方法
    • 父类引用指向子类对象

    多态是方法的多态属性没有多态性

    Person.java

    package com.oop.Demo07;
    
    public class Person {
    
        public void run(){
            System.out.println("run");
        }
    }
    

    Student.java

    package com.oop.Demo07;
    
    public class Student extends Person{
        @Override
        public void run() {
            System.out.println("son run");
        }
    
        public void eat(){
            System.out.println("eat");
        }
    
    }
    

    Application.java

    package com.oop;
    import com.oop.Demo07.Person;
    import com.oop.Demo07.Student;
    
    public class Application {
        public static void main(String[] args) {
            //一个对象的实际类型是确定的
            //new Student();
            //new Person();
    
            //可以指向的引用类型就不确定了
    
            //Student能调用的方法都是自己的或者继承父类的
            Student s1 = new Student();
    
            //Person父类型,可以指向子类,但是不能调用子类独有的方法
            Person s2 = new Student();// 父类的引用指向子类
            Object s3 = new Student();
    
    
            //对象能执行哪些方法,主要看对象左边的类型,和右边的关系不大。
            s2.run();//子类重写了父类的方法,执行子类的方法
            s1.run();
    
            s1.eat();
            ((Student) s2).eat();//强制类型转换
    
        }
    }
    

    多态注意事项:

    1. 多态是方法的多态,属性没有多态
    2. 父类和子类,有联系,类型转换异常!ClassCastException!
    3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1 = new son();
    4. 不可重写方法:
      1. static方法: 属于类,它不属于实例
      2. final方法:常量
      3. private方法:私有

    instanceof

    判断两个类之间是否存在父子关系

    Person.java

    package com.oop.Demo07;
    
    public class Person {
    
        public void run(){
            System.out.println("run");
        }
    }
    

    Teacher.java

    package com.oop.Demo07;
    
    public class Teacher extends Person{
    }
    

    Student.java

    package com.oop.Demo07;
    
    public class Student extends Person{
    
    }
    

    Application.java

    package com.oop;
    
    import com.oop.Demo07.Person;
    import com.oop.Demo07.Student;
    import com.oop.Demo07.Teacher;
    
    public class Application {
        public static void main(String[] args) {
            //Object > Person >Student
            Object object = new Student();
    
            System.out.println(object instanceof Student);//true
            System.out.println(object instanceof Person);//true
            System.out.println(object instanceof Object);//true
            System.out.println(object instanceof Teacher);//false
            System.out.println(object instanceof String);//false
            System.out.println("=========================");
    
            Person person = new Student();
            System.out.println(person instanceof Student);//true
            System.out.println(person instanceof Person);//true
            System.out.println(person instanceof Object);//true
            System.out.println(person instanceof Teacher);//false
            //System.out.println(person instanceof String);//编译错误
            System.out.println("=========================");
            Student student = new Student();
    
            System.out.println(student instanceof Student);//true
            System.out.println(student instanceof Person);//true
            System.out.println(student instanceof Object);//true
            //System.out.println(student instanceof Teacher);//编译错误
            //System.out.println(student instanceof String);//编译错误
    
    
        }
    }
    

    类型转化

    package com.oop;
    
    import com.oop.Demo07.Person;
    import com.oop.Demo07.Student;
    
    public class Application {
        public static void main(String[] args) {
            //类型之间的转化
            //子类转换为父类,可能会丢失自己的本来的一些方法
            Student student = new Student();
            Person person = new Student();
            //父转子,向下转型;强制转换
            ((Student)person).go();
            student.run();
        }
    }
    
    
    • 父类的引用指向子类的对象
    • 把子类转换为父类,向上转型
    • 把父类转换为子类,向下转型。强制转换

    static关键字详解

    Student.java

    package com.oop.Demo07;
    
    public class Student{
        //属性
        private static int age;
        private double score;
    
        //方法
        public void run(){
            go();
        }
    
    
        //静态方法和类一起加载
        public static void go(){
    
        }
    
        public static void main(String[] args) {
    
            //静态属性(方法)可以直接通过类名来调用,非静态属性(方法)需要new一个对象然后通过对象来调用
            Student s1 = new Student();
            System.out.println(s1.score);
            System.out.println(Student.age);
            System.out.println(age);//静态属性可以直接调用
    
    
            Student.go();
            go();//静态方法可以直接调用
            //Student.run(); 非静态的方法不能直接用类名来调用
            s1.run();
    
        }
    }
    

    Person.java

    package com.oop.Demo07;
    
    public class Person {
    
    
        {//赋初始值
            System.out.println("匿名代码块");//代码块(匿名代码块)
        }
    
    
    
        static {//只执行一次
           System.out.println("静态代码块");//静态代码块
       }
    
       public Person(){
           System.out.println("构造方法");
       }
    
        public static void main(String[] args) {
            Person person = new Person();
            //静态代码块-->匿名代码块-->构造方法
            System.out.println("==================");
            Person person1 = new Person();
    
    
        }
    
    }
    

    Test.java

    package com.oop.Demo07;
    import static java.lang.Math.random;
    import static java.lang.Math.PI;
    
    public class Test {
        public static void main(String[] args) {
            System.out.println(random());
            System.out.println(PI);
        }
    }
    

    抽象类

    • abstract修饰符可以用来修饰方法也可以用来修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
    • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
    • 抽象类不能使用new关键字来创建对象,它是用来让子类继承的。
    • 抽象方法,只有方法的声明,没有方法的实现,他是用来让子类实现的。
    • 子类继承抽象类,那么就必须要实现抽象类没有实现的方法,否则该子类也要声明为抽象类。

    Action.java

    package com.oop.Demo08;
    
    public abstract class Action {
        //抽象类依然有构造器
        public Action(){
    
        }
        //约束
        //abstract,抽象方法,只有方法名字,没有方法的实现
        public abstract void doSomething();
    
        /*
        1.不能new这个抽象类,只能靠子类去实现它:约束
        2.抽象类中可以写普通的方法
        3.抽象方法必须在抽象类中
        //抽象的抽象:约束
         */
    }
    

    A.java

    package com.oop.Demo08;
    
    public class A extends Action{
        @Override
        public void doSomething() {
    
        }
    }
    

    接口

    • 普通类:只有具体实现
    • 抽象类:具体实现和规范(抽象方法)都有
    • 接口:只有规范

    接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能...”的思想——如果你是汽车,则必须能跑。

    接口本质是契约

    接口是OOP的精髓,是对对象的抽象。

    设计模式所研究的,实际上就是如何合理的去抽象。

    声明接口的关键字是interface

    UserService.java

    package com.oop.Demo09;
    
    public interface UserService {
        //常量都是public static final的
        int age = 99;
    
        //接口中的所有定义的方法其实都是public abstract的
        void add(String name);
        void delete(String name);
        void update(String name);
        void query(String name);
    }
    

    TimeService.java

    package com.oop.Demo09;
    
    public interface TimeService {
        void timer();
    }
    

    UserServiceImpl.java

    package com.oop.Demo09;
    
    public class UserServiceImpl implements UserService,TimeService{
        @Override
        public void add(String name) {
    
        }
    
        @Override
        public void delete(String name) {
    
        }
    
        @Override
        public void update(String name) {
    
        }
    
        @Override
        public void query(String name) {
    
        }
    
        @Override
        public void timer() {
    
        }
    }
    

    接口作用:

    1. 约束
    2. 定义一些方法,让不同的人实现
    3. 接口中的所有定义的方法:public abstract
    4. 常量:public static final
    5. 接口不能被实例化,接口中没有构造器
    6. implements可以实现多个接口,必须重写接口中的方法

    内部类

    内部类即是在一个类的内部在定义一个类

    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类

    成员内部类

    Outer.java

    package com.oop.Demo10;
    
    public class Outer {
    
        private int id = 1;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
        public class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
    
            //获得外部类的私有属性
            public void getId(){
                System.out.println(id);
            }
        }
    
    
    }
    

    Application.java

    package com.oop;
    
    import com.oop.Demo10.Outer;
    
    public class Application {
        public static void main(String[] args) {
            Outer outer = new Outer();
    
            //通过这个外部类来实例化内部类
            Outer.Inner inner = outer.new Inner();
            inner.in();
            inner.getId();
    
    
        }
    }
    

    静态内部类

    Outer.java

    package com.oop.Demo10;
    
    public class Outer {
    
        private static int id = 1;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
        public static class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
    
            //获得外部类的私有属性
            public void getId(){
                System.out.println(id);
            }
        }
    
    
    }
    

    Application.java

    package com.oop;
    
    import com.oop.Demo10.Outer;
    
    public class Application {
        public static void main(String[] args) {
            Outer outer = new Outer();
    
            //通过这个外部类来实例化内部类
            
            //没加static之前
            // Outer.Inner inner = outer.new Inner();
            
            Outer.Inner inner = new Outer.Inner();
            inner.in();
            inner.getId();
    
    
        }
    }
    

    局部内部类

    Outer.java

    package com.oop.Demo10;
    
    public class Outer {
        public void method(){
    
            //局部内部类
            class Inner{
    
            }
        }
    }
    

    匿名内部类

    Test.java

    package com.oop.Demo10;
    
    public class Test {
        public static void main(String[] args) {
            //没有名字初始化类,不用把实例保存到变量中
            new Apple().eat();
    
            new UserService(){
                @Override
                public void hello() {
    
                }
            };
        }
    }
    
    class Apple{
        public void eat(){
    
        }
    }
    
    interface UserService{
        void hello();
    }
    
  • 相关阅读:
    常用Docker命令
    Ubuntu16.04安裝最新Nvidia驱动
    (转)5分钟让你明白“软链接”和“硬链接”的区别
    Centos7 Zabbix3.2集群安装
    Kettle定时抽取两个库中的两个表到目标库SYS_OPLOG表
    Elasticsearch Java API—多条件查询(must)
    logstash采集tomcat日志、mysql错误日志
    让Logstash每次都从头读文件及常见问题
    logstash之multiline插件,匹配多行日志
    spring security积累
  • 原文地址:https://www.cnblogs.com/kikikikikiku/p/14014089.html
Copyright © 2011-2022 走看看