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

    Java面向对象编程

    初识面向对象

    • 面向过程思想:
      • 步骤清晰简单,第一部步做什么,第二步做什么......
      • 面对过程适合处理一些较为简单的问题
    • 面向对象思想
      • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考,最后才对某个分类下的细节进行面向过程的思考
      • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
    • 对于描述复杂的事务,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统,但是具体到微观操作,仍然需要面向过程的思路去处理

    什么是面向对象

    • 面向对象编程简称OOP
    • 面向对象编程的本质:以类的方式组织代码,以对象的形式组织(封装)数据
    • 抽象
    • 三大特性:封装继承多态
    • 从认识的角度考虑是先有对象后有类。对象是具体的事务;类是抽象的,是对对象的抽象
    • 从代码的角度考虑是先有类后有对象。类是对象的模板

    方法的回顾和加深

    方法的定义

    • 修饰符
    • 返回类型
    • break:跳出switch,结束循环。return:结束方法,返回一个结果
    • 方法名:驼峰命名法,见名知意
    • 参数列表:(参数类型,参数名),(参数类型...)
    • 异常抛出
    例子1
    //Demo01 类
    public class Demo01 {
        //main 方法
        public static void main(String[] args) {    }
        /*
        修饰符 返回值类型 方法名(参数...){
            //方法体
            return 返回值;
        }
         */
        public String sayhello() {
            return "hello world";
        }
        public int max(int a, int b) {
            return a > b ? a : b;//三元运算符
        }
        //第一个遇到的异常:数组下标越界Arrayindexoitofbounds
        //完整的方法
        public void readFiles(String file) throws IOException {    }
    }
    

    方法的调用

    • 静态方法与非静态方法

      例子2
      public class Demo02 {
          //静态方法  static
          //非静态方法
          public static void main(String[] args) {
              //实例化类 new
              //对象类型 对象名 = 对象值
              Student student = new Student();
              student.say();
          }
          //static和类一起加载
          public static void a() {
      //        b();//报错
          }
          //类实例化后才存在
          public void b() {
              a();//没报错
          }
      }
      //学生类
      public class Student {
          //方法
          public void say() {
              System.out.println("学生说话了");
          }
      }
      
    • 形参与实参

      例子3
      public class Demo03 {
        public static void main(String[] args) {
            int a = 1;
            int b = 2;
            int add = Demo03.add(a, b);
            System.out.println(add);
        }
        public static int add(int a, int b) {
            return a + b;
        }
      }
      
    • 值传递

      例子4
      //值传递
      public class Demo04 {
          public static void main(String[] args) {
              int a = 1;
              System.out.println(a);//1
              Demo04.change(a);
              System.out.println(a);//1
          }
          //返回值为空
          public static void change(int a) {
              a = 10;
          }
      }
      
    • 引用传递

      例子5
      //引用传递:对象。本质还是值传递
      public class Demo05 {
          public static void main(String[] args) {
              Person person = new Person();
              System.out.println(person.name);//null
              Demo05.change(person);
              System.out.println(person.name);//jdl
          }
          public static void change(Person person) {
              //person是一个对象,指向->Person person = new Person();这是一个具体的人,可以改变属性
              person.name = "jdl";
          }
      }
      //定义了一个Person类,有一个属性name
      class Person{
          String name;//默认值null
      }
      
    • this关键字

    对象的创建分析

    类与对象的关系

    • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不代表某一个具体的事物
    • 对象是抽象概念的具体实例。能够体现出特点、展现出功能的是具体的实例,而不是一个抽象的概念
    例子6
    //一个项目应该只存在一个main方法
    public class Application {
        public static void main(String[] args) {
            //类:抽象的,需要实例化
            //类实例化后会返回一个自己的对象
            //student对象就是一个Student类的具体实例
            Student xm = new Student();
            Student xh = new Student();
            xm.name = "小明";
            xm.age = 3;
            System.out.println(xm.name);
            System.out.println(xm.age);
            xh.name = "小红";
            xh.age = 3;
            System.out.println(xh.name);
            System.out.println(xh.age);
        }
    }
    //学生类
    public class Student {
        //属性:字段
        String name;
        int age;
        //方法
        public void study(){
            System.out.println(this.name+"在学习");
        }
    }
    

    创建与初始化对象

    • 使用new关键字创建对象
    • 使用new关键字创建的时候,出了分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
    • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,并且构造器有以下两个特点
      1. 必须和类的名字相同
      2. 必须没有返回类型,也不能写void
    • 构造器必须要掌握
    例子7
    public class Application {
        public static void main(String[] args) {
            //new实例化了一个对象
            Person person = new Person();
            System.out.println(person.name);//jdl
        }
    }
    public class Person {
        //一个类,即使什么都不写,也会存在一个方法
        //显示的定义构造器
        String name;
        //1.使用new关键字,本质是在调用构造器
        //2.用来初始化值
        public Person(){
            this.name = "jdl";
        }
        //有参构造:一旦定义了有参构造,无参构造就必须显示定义
        public Person(String name){
            this.name = name;
        }
        //alt + insert快捷键,自动生成构造器
    }
    

    总结:

    ​ 构造器:

    ​ 1.与类名相同

    ​ 2.没有返回值

    ​ 作用:

    ​ 1.使用new关键字,本质是在调用构造器

    ​ 2.初始化对象的值

    ​ 注意:

    ​ 1.定义有参构造后,如果想使用无参构造,要手动再定义一个无参构造

    ​ 快捷键alt+insert,自动生成一个构造器

    创建对象内存分析

    例子8
    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();
        }
    }
    public class Pet {
        public String name;
        public int age;
        //默认有一个无参构造
        public void shout() {
            System.out.println("叫了一声");
        }
    }
    

    面向对象的三大特性

    封装

    • 该露的露,该藏得藏
      • 程序设计要追求“高内聚,低耦合”。
        • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
        • 低耦合:仅暴露少量的方法给外部使用
    • 封装(数据的隐藏)
      • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这成为信息隐藏
    • 重点:属性私有,get/set

    封装的作用:

    1. 提高程序的安全性,保护数据
    2. 隐藏代码的实现细节
    3. 统一接口
    4. 增加系统的可维护性
    例子9
    public class Application {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("jdl");
            System.out.println(s1.getName());
            s1.setAge(120);
            System.out.println(s1.getAge());
        }
    }
    public class Student {
        //属性私有
        private String name;//名字
        private int id;//学号
        private char sex;//性别
        private int age;//年龄
        //提供一些可以操作这个属性的方法
        //提供一些public的get、set方法
        //get 获得数据
        public String getName() {
            return this.name;
        }
        //set 给数据设置值
        public void setName(String name) {
            this.name = name;
        }
        //alt+insert快捷键,快速设置get、set
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            if (age > 120 || age < 0) {
                this.age = 3;
            } else {
                this.age = age;
            }
        }
    }
    

    继承

    • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
    • extends的意思是“扩展”。子类是父类的扩展
    • JAVA中类只有单继承,没有多继承
    • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等
    • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
    • 子类和父类之间,从意义上讲应该具有“is a”的关系
    子类继承了父类,就会拥有父类的全部方法
    快捷键ctrl + H,打开层次结构,查看类与类之间的继承关系
    
    例子10
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.say();
            System.out.println(student.getMoney());
        }
    }
    public class Person {
        //public
        //protected
        //default
        //private
        private int money = 10_0000_0000;
        public void say(){
            System.out.println("说了一句话");
        }
        public int getMoney() {
            return money;
        }
        public void setMoney(int money) {
            this.money = money;
        }
    }
    public class Student extends Person { }
    

    object类

    • 在Java中,所有的类都默认直接或间接继承Object类

    super

    • 注意点:

      1. super调用父类的构造方法,必须在构造方法的第一行
      2. super必须只能出现在子类的方法或者二构造方法中
      3. super和this不能同时调用构造方法
    • 与this的区别:

      1. 代表的对象不同

        this:本身调用者这个对象

        super:代表父类对象的引用

      2. 前提:

        this:没有继承也可以使用

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

      3. 构造方法:

        this():本类的构造

        super():父类的构造

    例子11
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.test1("杰达鲁");
            student.test2();
        }
    }
    public class Student extends Person {
        private String name = "llk";
        public void test1(String name){
            System.out.println(name);
            System.out.println(this.name);
            System.out.println(super.name);
        }
        public void print(){
            System.out.println("Student");
        }
        public void test2(){
            print();
            this.print();
            super.print();
        }
        public Student() {
            //隐藏代码:调用了父类的无参构造
            //调用父类的构造器,必须要在子类构造器的第一行
            super();
            System.out.println("Student无参");
        }
    }
    public class Person {
        protected String name = "jdl";
        public void print(){
            System.out.println("Person");
        }
        public Person() {
            System.out.println("Person无参");
        }
    }
    

    方法重写

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

      1. 方法名必须相同
      2. 参数列表必须相同
      3. 修饰符:范围可以扩大:public > Protected > Default > private
      4. 抛出的异常:范围可以被缩小,不能扩大
    • 子类的方法与父类必须要一致,方法体不同

    • 重写都是方法的重写,与属性无关

    • 为什么需要重写:

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

    快捷键alt+insert:override

    例子12
    public class Application {
        public static void main(String[] args) {
            //静态方法与非静态方法的区别很大
            //静态方法:方法调用只和定义数据的类型有关
            A a = new A();
            a.test();//A=>test()
            //父类的引用指向了子类
            B b = new A();//子类重写了父类的方法
            b.test();//B=>test()
        }
    }
    public class A extends B{
        //Override 重写
        @Override //注解,有功能的注释
        public void test() {
            System.out.println("A=>test()");
        }
    }
    public class B {
        public void test(){
            System.out.println("B=>test()");
        }
    }
    
    • 不能重写的方法
      1. static:静态方法,属于类,不属于实例
      2. final:常量
      3. private:私有方法

    多态

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

    • 一个对象的实际类型是确定的,但可以指向对象的引用的类型(父类,有关系的类)有很多

    • 多态存在的条件

      • 有继承关系
      • 子类重写父类方法
      • 父类引用指向子类对象
    • 注意多态是方法的多态,属性没有多态性

    • instanceof:(类型转换),引用类型

    例子13
    public class Application {
        public static void main(String[] args) {
            //一个对象的实际类型是确定的
            //可以指向的引用类型不确定,父类的引用指向子类
            Student s1 = new Student();
            Person s2 = new Student();
            Object s3 = new Student();
            s2.run();//子类重写了父类的方法,执行了子类的方法
            s1.run();
            //对象能执行哪些方法主要看左边的类型,和右边关系不大
            ((Student)s2).eat();
            s1.eat();
        }
    }
    public class Student extends Person{
        @Override
        public void run() {
            System.out.println("son");
        }
        public void eat(){
            System.out.println("eat");
        }
    }
    public class Person {
        public void run(){
            System.out.println("run");
        }
    }
    
    • 注意事项
      1. 多态是方法的多态,属性没有多态
      2. 父类和子类要有联系,不能随便转换。类型转换异常:ClassCastException
      3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象: Father f1 = new Son();

    instanceof

    1. 父类引用指向子类的对象

    2. 把子类转换为父类,向上转型

    3. 把父类转换为子类,向下转型;强制转换

    4. 方便方法的调用,减少重复代码

    Object object = new Student();
    System.out.println(object instanceof Student);
    

    static(补充)

    public class Person {
        //第二个执行
        {
            //代码块(匿名代码块),可以用来赋初始值
            System.out.println("匿名代码块");
        }
    
        //第一个执行,只执行一次
        static {
            //代码块(静态代码块)
            System.out.println("静态代码块");
        }
    
        //第三个执行
        public Person() {
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Person p1 = new Person();
            System.out.println("----------");
            Person p2 = new Person();
        }
    }
    

    抽象类和接口

    抽象类

    public abstract class Action {
        //约束
        //abstract抽象方法:只有方法名,没有方法的实现
        public abstract void doSomeSthing();
    }
    //继承了抽象类的子类,必须要实现抽象类的方法,除非子类也是抽象类,那么由下一个子类实现方法
    public class A extends Action{
        @Override
        public void doSomeSthing() {
    		System.out.println("hello world");
        }
    }
    
    1. 抽象类不能new,只能靠子类实现
    2. 抽象类中可以写普通得方法
    3. 抽象方法必须再抽象类中
    4. 抽象的抽象:约束
    5. 抽象类有构造方法
    6. 存在的意义:规范代码,提高开发效率

    接口的定义和实现

    • 普通类:只有具体实现

    • 抽象类:具体实现和规范(抽象方法)都有

    • 接口:只有规范。自己无法写方法,专业的约束。可以让约束和实现分离,面向接口编程

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

    • 接口的本质是契约

    • OO的精髓,是对对象的抽象,最能体现这一点的就是接口。

    • 声明类的关键字是class,声明接口的关键字是interface

    作用:

    1. 约束
    2. 定义一些方法,让不同的人实现
    3. 接口中的方法都是public abstract
    4. 接口中的常量都是public static final
    5. 接口不能被实例化,接口中没有构造方法
    6. implements可以实现多个接口
    7. 必须要重写接口中的方法
    
    //interface定义的关键字,接口都需要实现类
    public interface UserService {
        //接口中的所有定义其实都是抽象的 public abstract
        void add(String name);
        void delete(String name);
        void update(String name);
        void query(String name);
    }
    public interface TimeService {
        void timer();
    
        //接口中定义的属性都是常量 public static final
        int AGE = 99;
    }
    //类可以实现接口:implements 接口
    //实现了接口的类,就需要重写接口中的方法
    //利用接口实现多继承
    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() {    }
    }
    

    内部类

    • 内部类就是在一个类的内部再定义一个类
    • 内部类有成员内部类,静态内部类,局部内部类,匿名内部类
    public class Outer {
        private int id = 10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
        public class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
    
            //获得外部类的私有属性和私有方法
            public void getID(){
                System.out.println(id);
            }
        }
    
        //局部内部类
        public void method(){
            class Inner{
                public void in(){
    				System.out.println("0");
                }
            }
        }
    }
    
    //一个java类中可以有多个class类,但是只能有一个public class
    class A{ }
    
    public class Test {
        public static void main(String[] args) {
            //没有名字去初始化类,不用将实例保存到变量中
            new Apple().eat();
    
            //匿名内部类
            UserService userService = new UserService(){
                @Override
                public void hello() {
                    System.out.println("hello world");
                }
            };
        }
    }
    
    class Apple{
        public void eat(){
            System.out.println("1");
        }
    }
    
    interface UserService{
        void hello();
    }
    
    public class Application {
        public static void main(String[] args) {
            Outer outer = new Outer();
            //通过外部类实例化内部类
            Outer.Inner inner = outer.new Inner();
            inner.in();
            inner.getID();
        }
    }
    
  • 相关阅读:
    leetcode 33. Search in Rotated Sorted Array
    leetcode 32. Longest Valid Parentheses
    leetcode 28. Implement strStr()
    leetcode 27. Remove Element
    leetcode 26. Remove Duplicates from Sorted Array
    leetcode 24. Swap Nodes in Pairs
    leetcode 22. Generate Parentheses
    树莓派的频率管理和热控制
    sql执行insert插入一条记录同时获取刚插入的id
    全程直播个人博客重构过程,采用springboot+dubbo+jpa技术栈。
  • 原文地址:https://www.cnblogs.com/mooncell/p/14662911.html
Copyright © 2011-2022 走看看