zoukankan      html  css  js  c++  java
  • JAVA面向对象初级

    Java的面向对象的特征

    1、封装(隐藏)

      对类中成员属性进行隐藏(私有化),对类中的成员方法公共。
    

    2、继承

      一个类A可以继承另一个类B,这里类A就是类B的子类,类A可以继承类B的属性和方法,也可以定义自己的                  
    属性和方法
    

    3、多态

      为了适应需求的多种变化,类可以呈现多种形态,使代码更加通用
    

    1、封装

      为了提高类的隐蔽性,对类实现的细节隐藏,提供外部访问的接口即可,提高代码的可扩展性
      生活中的封装:例如笔记本的内部结构同一封装了,一般人使用笔记本时不需要了解笔记本的结构,而是            
    直接开机关机使用
    

    对代码的封装包括两层意思:

    1、对类的成员属性的封装 :

    ​ 将属性私有化(private),提供对属性的访问给属性添加公用的getter和setter方法

    2、对代码的封装:

    ​ 为了提高代码的复用性,尽量使用方法加参数传递对代码进行封装,并使该方法公有(public)
    public class People {
    private String pname;
    private int age;
    private String sex;
    // 提供 getter 和 setter
    public String getPname(){
    return pname;
    }
    public void setPname(String pname){
    this.pname=pname;
    }

    public int getAge(){
        return age;
    }
    public void setAge(int age){
        // 对成员属性的隐蔽性 可以防止随意对属性更改
        if(age>100 || age<0){
            System.out.println("赋值的年龄不合法");
            return;
        }
        this.age = age;
    }
    
    public String getSex(){
        return sex;
    }
    public void setSex(String sex){
        this.sex= sex;
    }
    
    
    // 通常为了方便给属性赋值,会提供有参构造
    public People(String pname ,int age,String sex){
        this.pname = pname;
        this.age = age;
        this.sex = sex;
    }
    public People(){
    
    }
    

    }

    对于boolean类型的属性,需要使用isXxx返回属性的值。
    封装的有点:
    1、良好的封装可以减少代码的耦合性
    2、对类中封装的代码可以自由修改,而不会影响其他类
    3、最大程度提高类中属性的隐蔽性 和对属性的控制

    2、访问修饰符的权限

      用于修饰类,属性,方法的关键字都称为访问修饰符
      2.1、public 公共的
            可被同一个项目的所有类访问(项目可见性)
      2.2protect:受保护的
            可以被自身的类访问
            可以被同包下的其他类访问
            对于不同包的,存在父子关系的子类可以访问
      2.3default 默认的
            可以被自身访问
            可以被同包下的其他类访问
      2.4private:私有的
            自能被自身类访问
    
    访问修饰符 同一个类 同一包不同类(子类或非子类) 不同包的子类 不同包
    public
    protected ×
    默认 × ×
    private × × ×

    3、static关键字

      static表示“静态”,它可以修饰 属性,方法,代码块,在一个类中除了可以定义属性、成员方法和构造器以外,还可以定义静态的部分(静态属性,静态方法,静态代码块)
      static修饰属性:称为静态属性或者类的属性
      static修饰方法:称为静态方法或者类方法
      static修饰语句块:称为静态代码块
      static修饰的组件不需要通过对象访问,而是直接通过类名访问,在类一加载时会给static修饰的属性和方法分配内存区,这个内存分布在静态内存区中。后续所有对象操作的时同一个内存区
    

    案例一:
    `public class Student {
    // 成员属性
    String name;
    // 静态属性 通常static写在public的后面
    static int age=20;
    // 静态代码块
    static{
    System.out.println("这是静态代码块,在类一加载时,就会被执行,且只执行一次");
    }

    //成员方法  : 既可以访问 成员属性,也可以访问静态属性
    public void getInfo(){
        System.out.println("姓名:"+name +" 年龄:" +age);
    }
    // 静态方法 : 只能访问静态属性,不能访问成员属性(非静态属性
    //   这是为什么? 由于成员属性的存在需要依赖对象 ,
    // 静态属性和静态方法在创建对象之前就必须初始化并分配内存
    public static void getStaticInfo(){
       // System.out.println("姓名:"+name);  成员属性不能被访问
        System.out.println("静态属性:"+age);
    }
    
    
    public Student(){
        System.out.println("无参构造器");
    }
    
    // 构造代码块
    {
        System.out.println("构造代码块");
    }
    
    
    public static void main(String[] args) {
        System.out.println("访问静态属性:"+Student.age);
        // 访问静态方法
        Student.getStaticInfo();
    

    // 类的组件执行顺序
    // 类编译成.class文件被JVM的类加载器加载-》
    // 从上往下初始化static修饰的组件
    // (静态属性,静态代码块,静态方法,其中静态方法调用才执行,静态属性和静态代码块直接分配内存)-》
    // --》构造代码块-》执行构造器 -》初始化成员属性,成员方法
    Student stu1 = new Student();
    stu1.name="张三";
    // 静态属性可以通过类名访问,也可以通过对象名访问
    stu1.age=21;
    System.out.println(stu1);

        Student stu2 = new Student();
        stu2.name="王麻子";
        stu2.age=22;
        System.out.println(stu2);
    
        System.out.println(stu1.name);
        System.out.println(stu1.age); //   22
    
        System.out.println(stu2.name); //王麻子
        System.out.println(stu2.age); // 22
    
        System.out.println(Student.age);//  22
    
    }
    
    
    }`
    

    案例二:静态的变量 在同一个内存中
    `public class People {
    double height;
    static int score;
    static{
    score++; // 1
    }
    public void setScore(){
    score++; //81 86
    }
    public static void setScore2(){
    score++;
    }

    public static void main(String[] args) {
         People p1 = new People();
         p1.score=80;//静态属性
         p1.setScore();
         People.score=85;
         p1.height= 1.75;
         People p2 = new People();
         p2.setScore(); //86
         p2.height= 1.80;
    
        System.out.println(p1.score); // 86
        System.out.println(p1.height); // 1.75
    
        System.out.println(p2.score);//86
        System.out.println(p2.height);// 1.80
    
    }
    

    } 案例三:构造代码块和静态代码块的执行顺序public class UserInfo {
    // 关于静态的组件 从上往下执行

    // 静态属性  需要先初始化 ,需要new一个对象
    static UserInfo u = new UserInfo(); // 先执行构造代码块 在执行构造器
    static{
        System.out.println("这是静态代码块,只执行一次");
    }
    
    public UserInfo(){
        System.out.println("这是无参构造器");
    }
    {
        System.out.println("构造代码块");
    }
    
    public static void main(String[] args) {
         // 结果
        UserInfo u = new UserInfo();
    }
    

    }
    `
    结果:构造代码块
    这是无参构造器
    这是静态代码块,只执行一次
    构造代码块
    这是无参构造器

    4、继承

    4.1概念

      当类中都存在相同的属性和行为时,可以将共有的属性定义到一个新的类中,让其他类附庸这个新类的属性和行为,这种关系就是继承关系
      当满足XXX是一个XXX的时候,也是继承关系,例如 苹果是一种水果,其中水果就是父类,苹果就是子类,水果有多种,而苹果只是水果的一种,所以苹果继承水果
      其中被继承的类时父类(超类,基类),继承父类的是子类(新类,派生类)
    

    4.2、继承的语法

      先定义父类
    

    public class 父类{ }
    在定义子类
    public class 子类 extends 父类{ }

    4.2.1子类继承父类,子类拥有父类的哪些属性和方法?

      可访问: 子类拥有父类的共有的属性和方法, 同包下面的属性和方法,不同包下的受保护的也可以访问 
    

    不可访问: 其中子类不能继承 父类的私有的属性和方法、不同包的默认属性和方法 ,不能继承父类的构造器

    4.2.2 子类继承父类,子类如何访问父类的属性和方法

    属性: 子类通过super 关键字访问父类的属性 ,子类通过this关键字访问自己的属性

    方法:子类通过super挂件自方法父类的方法, 子类通过this关键字访问自己的方法

    注意: 这里的this和super可以省略,省略后子类通过“就近原则”访问属性和方法(子类中存在就访问子类的,子类中不存在,就访问父类的。)

    super.属性

    super.方法(参数)

    构造器:子类通过super([参数]) 调用父类的构造器, 子类通过this([参数])调用 自己类的其他构造器,其中 super(参数[]) 必须写在子类构造器的第一行

    通过在子类构造器手动调用父类的有参构造器给父类的属性赋值
    `public class Employee {
    String ename="王麻子";//员工姓名
    double sal=5000 ; // 员工薪资

     public Employee(String ename,double sal){
        this.ename = ename;
        this.sal = sal;
    }
    

    } public class Manager extends Employee{
    // 奖金
    private double comm;
    public Manager(String ename ,double sal ,double comm){
    // 如何覆盖父类的无参构造器 ,手动调用父类的有参构造
    super(ename ,sal); // 只能写在第一句
    this.comm = comm;
    }
    }`
    注意:子类构造器中默认调用父类的无参构造器

    4.2.3、Java中只能是单继承,一个类只能有一个直接父类的父类,可实现多层继承

      子类->父类->父类的父类
      Pupil->Student->People
        创建子类对象时,优先创建父类对象,再创子类对象, 执行顺序   最上层父类的构造器 -》 父类构造器 -》子类构造器。  
    

    ​ 扩展问题:当一个类中存在static元素时,它们的执行顺序是如何?

    顺序: 最上层父类的静态块 - 》 父类的静态块-》 子类的静态块- 》最上层 父类的构造块和构造方法

    -》父类的构造块和构造方法- 》 子类的构造块和构造方法
    `public class People {
    static{
    System.out.println("People的静态语句块");
    }
    public People(){
    System.out.println("People类的无参构造器");
    }
    {
    System.out.println("People的构造语句块");
    }
    }

    public class Student extends People{
    static{
    System.out.println("Student 的静态语句块");
    }
    public Student(){
    // 默认调用父类的构造器
    System.out.println("Student的无参构造器");
    }
    {
    System.out.println("Student的构造语句块");
    }
    }
    public class Pupil extends Student {
    static{
    System.out.println("Pupil的静态语句块");
    }
    public Pupil(){
    // 调用它父类的无参构造器
    System.out.println("Pupil类的无参构造器");
    }
    {
    System.out.println("pupil的构造器语句块");
    }
    } public static void main(String[] args) {
    //创建Pupil对象
    Pupil pupil = new Pupil();

    }`
    

    结果:People的静态语句块
    Student 的静态语句块
    Pupil的静态语句块
    People的构造语句块
    People类的无参构造器
    Student的构造语句块
    Student的无参构造器
    pupil的构造器语句块
    Pupil类的无参构造器

    4、重写

      子类可以继承父类的方法,但是父类的方法不能满足子类的需要时,子类可以重写父类的方法
      重写的必要条件:
      1、两个方法名必须相同,且存在不同类中(父子关系的类)
      2、子类重写的父类的方法,其方法的参数和返回值必须完全一样,方法的具体实现可不一样
      3、访问修饰符必须大于或等于父类的修饰符
    

    注意:子类的对象调用父类方法时,如果子类重写了父类的方法,则执行子类的方法,没有重写就执行父类的方法。

    面试题:
    说一下方法的重写与重载的区别?
    1、重写必须存在于父子关系中的不同类,重载存在同类中
    2、重写必须满足方法相同,且参数相同,返回值相同,重载满足方法名相同,参数不同,与返回值无关。
    3、重写的访问修饰符必须大于等于父类,重载没有要求

    二、抽象类

    1、定义

      在已有类的基础上,由于特殊情况将该类型设置为抽象的,这个类就是抽象类
      语法:
      `puclic abstract class类{
            //类的元素
      }`
      什么情况下需要定义抽象类?
      1、当这个类不需要创建具体的实例时,可将类定义为抽象的
      2、当这个类中存在没有实现的方式时(没有方法体的方法),可以将这个类定义为抽象类
      ##2、抽象类的特点
      2.1抽象类不能实例化(不能new),通常抽象类被当做父类使用
      2.2抽象类中可以有抽象方法(没有方法体的方法)也可以有普通方法
      2.3抽象被被当做父类时,它的子类必须重写父类的抽象方法
      `public abstract class Fruit{
      private String color;
      
      public String getColor(){
      return color;
      }
      public String setColor(){
      this.color=color;
      }
      //水果的甜度 由于不知道是什么水果,所以水果的甜度未知,可以定义为抽象方法
      //抽象方法
      public abstract void getSweet();
      }`
      `public class Apple extengds Fruit{
      //子类重写(实现)父类的抽象方法
      public void getSweet(){
      System.out.println("这个水果有点甜");
      }
      }`
    
      `public class Lemon extends Fruit{
      public void getSweet(){
            System.out.println("这个水果有点酸,想想都觉得酸");
      }
      }`
      `public static void mian(String[] args){
      //抽象类不能实例化
      //Fruit fruit = new Fruit();
      //创建子类对象
      Apple apple=new Apple();
      apple.setColor("红色");
      apple.getSweet();
      System.out.println(apple.getColor());
    
      Lemon lemon = new Lemon();
      lemon.setColor("黄色");
      lemon.getSweet();
      System.out.println(lemon.getColor());
      }`
    

    面试题:
    抽象方法和非抽象方法的区别
    回答:抽象方法没有方法体,需要使用abstract修饰,只能写在抽象类中
    非抽象方法就是普通方法(成员方法或静态方法),可以写在抽象类或者普通类中。

    三、接口

    1、定义

      接口用于对于某件事物的功能的声明,而没有市县局提功能,接口提供对软件开发的标准规范。
      利用接口的“多实现”完成Java的单一继承
    

    2、接口语法

      `public interface 接口名{
      抽象方法定义
      }`
      一个类实现该接口,必须实现接口的所有方法
      `public class 实现类名  implements 接口名{
     实现接口的所有方法
      }`
      接口的好处:
      1、为了规范实现类的行为,让所有的方法都通过接口定义
      2、为了提高代码的可扩展性
    

    接口定义实现类的对象只能调用接口中定义的方法,实现类定义的对象既可以调用实现类的方法,也可以调用酒类的方法。

    3、接口中的成员组成部分 特点

      接口中定义的变量默认全部是 public static final修饰的
      接口中的静态方法可以直接调用。
      接口中不能写构造器(因为接口不能实例化,不需要构造器)
      接口中的方法全部都是抽象方法,在JDK8以后可以定义default的非抽象方法
      
      案例1:一个类既可以继承一个类  也可以实现多个接口
      `//定义一个门类,定义一个防盗门,它具有防盗的功能,如何翻到(防盗功能中可以 拍照,密码是)
      //门本身有开门,关门功能`
      案例2:一个类可以实现多个接口,中间用逗号分隔(这个类要实现接口的所有方法)
      `/**
       *  程序员身份
       */
      public interface Programer {
          public void takeMoney();
      }
      /**
       * 厨师
       */
      public interface Cooker {
     /**
     * 做好吃
     */
    public void makeFood();
      }
      public interface Driver {
    // 功能
    public void driverCar();
    
    public void takeMoney();
      }`
      `public class People implements Programer ,Cooker ,Driver {
    
    private String name;
    public People (String name){
        this.name = name;
    }
    @Override
    public void makeFood() {
        System.out.println("做好吃的");
    }
    
    @Override
    public void driverCar() {
        System.out.println("开车的功能");
    }
    
    @Override
    public void takeMoney() {
        System.out.println("赚钱的功能");
    }
    }`
     ` public static void main(String[] args) {
         People people = new People("袁巍巍");
         people.takeMoney();
         people.makeFood();
         people.driverCar();
    }`
    案例3:一个接口可以继承 接口,或多个接口(接口可以多继承)
      一个员工接口 一个程序员(由于程序员时员工,所以程序员可以继承员工接口)
      一个人使员工也是程序员(People是员工也是程序员)
    

    四、多态

      多态:继Java面向对象中封装,集成之后的第三个特征
      生活中的多态:同一个行为,例如跑,人是两条腿跑,动物是四条腿或两条腿跑,飞的行为不同是事物非得方式也不同,飞机费,小鸟飞,无人机飞都不一样,同一种行为对于不同的事物呈现的不同形态就是多天的表现。
    

    1、定义

      同一种行为,具有多个不同的表现形式
    

    2、实现多态的前提

      基于继承关系或基于实现关系的
      子类或实现类必须对方法进行重写(没有重写的方法 不具有多态行为)
      父类的引用指向子类对象(接口的引用指向实现类的对象)
    

    3、多态的对象转型

      1、子类对象转父类对象时,称为向上转型是默认转换,自动转型
      ` Cat cat = new Cat();
           // 猫类 可以是一只动物     an4的本质还是 猫对象
          Animal an4 = cat;    // 子类对象转成父类对象 ,是自动转型
           cat.eat();
           an4.eat();`
      2、父类的引用转成子类对象,称为向下转型,需要强转,为了避免转换错误,需要先判断数据类型是否匹配
      ` // 创建一个动物类, 将动物类转成子类引用
           Animal an5 = new Cat();
          //  an5.catchMouse(); // 动物类型对象不能访问 它子类特有的方法
          if(an5 instanceof Cat) {
              Cat cat2 = (Cat) an5;
              cat2.eat();
              cat2.catchMouse();
          }
          if(an5 instanceof  Dog) {
              Dog dog2 = (Dog)an5;
          }else{
              System.out.println("不能转成dog");
          }`
      instanceof:判断该对象是否属于这个类型
      为什么需要做类型转换呢?有时候我们需要调用子类特用的方法时必须用子类的引用。所有多态对象下父类应用需要强转。
      
      为了避免ClassCastException的发生,Java提供了instanceof关键字,给引用变量做类型的校验,格式如下:
      `变量名 instanceof 数据类型如果变量属于该数据类型,返回true。
    
      如果变量不属于该数据类型,返回false`
    

    4、在多态环境性,方法和属性的调用规则

      属性:当子类和父类中存在相同属性时,以 对象的左边引用类型为依据,所谓“看左边”
      方法:以当前new出来的对象为依据,如果方法重写了,就调用子类方法,如果方法没有重写,就调用父类方法
      静态方法:无论方法是否有重写,都以对象左边的引用类型为依据。
      `public class Student extends  People  {
      int age =20;
    
    @Override
    public void showAge() {
        this.age++;
        System.out.println("年龄:"+this.age+" ----"+super.age);
    
    }
    // 重写的静态方法
    public static void  method1(){
        System.out.println("method1------------  重写后的 方法");
    }
    

    } public static void main(String[] args) {
    People p1 = new People();
    System.out.println(p1.age);// 18
    p1.showAge(); // 对象的本质people 调用people

       People p2 = new Student();
      System.out.println( p2.age);// 18
      p2.showAge(); // 本质student ,且重写了 调Student
      p2.sleep();  // 本质student  ,没重写,调用people
    
        Student p3 = (Student)p2;
     System.out.println( p3.age); // 20
        p3.showAge(); // 本质student ,且重写了 调Student
    
        People p4 = p3;
     System.out.println( p4.age); // 18   看左边
        p4.showAge(); // 本质student ,且重写了 调Student
    
      }`
    

    结论:
    18
    年龄:18
    18
    年龄:21 ----18
    睡觉方法。。。。。
    21
    年龄:22 ----18
    18
    年龄:23 ----18
    `public static void main(String[] args) {
    People p1 = new People();
    p1.method1();
    p1.method2();

      People p2 = new Student();
      p2.method1();
      p2.method2();
    
      Student p3 = (Student)p2;
      p3.method1();
      p3.method2();
    
      }`
    

    结论:
    method1------------
    method2---------
    method1------------
    method2---------
    method1------------ 重写后的 方法
    method2---------

    总结常见面试题:
    1、抽象类与接口的区别

    ​共同点: 它们都是抽象的,都不能实例化

    区别:

    ​ 1、抽象类是类 使用abstract修饰,接口使用interface定义

    ​ 2、抽象类中可以包含抽象方法和普通方法, 接口中是纯粹的抽象类,都是抽象方法,除使用default定义以外

    ​ 3、子类继承抽象类,必须实现抽象类的方法,或者自身变为抽象类

    **​ 接口中是实现关系,实现类必须实现接口的所有方法,接口的变量是public static final **

    2、重载和重写的区别?

    3、在java中如何实现多态(多态的前提条件)?

    4、final的作用

    ​final修饰变量 定义为常量

    ​final 修饰方法 不能被重写

    ​final 修饰类 则不能被其他子类继承

  • 相关阅读:
    git的相关命令
    vue资料链接
    自定义小程序底部菜单
    物联网开发日记四:原理图2
    物联网开发日记三:原理图1
    物联网开发日记二:设计系统结构
    物联网开发日记一:准备工作
    mybatis不使用@Param有人报错有人却不报错问题
    最简单的js包装对象、ajax请求
    java文字转拼音、首字母缩写
  • 原文地址:https://www.cnblogs.com/zzk201/p/13801223.html
Copyright © 2011-2022 走看看