java面向对象&异常

java面向对象&异常

一. 面向对象

1.1 面向过程&面向对象

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

1.2 什么是面向对象

  • 面向对象编程(Object-Oriented Programming, OOP)

  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

  • 抽象

  • 三大特性:

    • 封装
    • 继承
    • 多台
* 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象 * 从代码运行角度考虑是先有类后有对象。类是对象的模板。

1.3 方法调用

!非静态方法可以调用静态方法

!但是静态方法不可以调用非静态方法

原因:静态方法同类创建时就加载完成了,而非静态方法是在类实例化时才进行加载.

1.4 类与对象的关系

  • 类是一种抽象的数据类型,它是对某-类事物整体描述/定义,但是并不能代表某- 个具体的事物.
    • 动物、植物、手机、电脑....
    • Person类、Pet类. Car类等,这些类都是用来描述/定义某-类具体的事物应该具备的特
      点和行为
  • 对象是抽象概念的具体实例
    • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
    • 能够体现出特点展现出功能的是具体的实例,而不是一个抽象的概念

1.5 创建与初始化对象

  • 使用new关键字创建对象
  • 使用new关键宇创建的时候,除了分配内存空间之外,还会给创建好的对象进行就认的初始化
    以及对类中构造器的调用。
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩
    个特点:
    1. 必须和类的名字相同
    2. 必须没有返回类型,也不能写void
    3. new本质在调用构造方法
    4. 初始化对象的值
    5. 定义有参构造后,如果想使用无参构造,显示的定义一个无参构造
  • 构造器必须掌握
  • 快捷键alt+insert
  • !char类型初始化u0000
    //一个类即使什么也不写它也会存在一个方法
    //显示的定义构造器
    String name;

    //实例化初始值
    //1.使用new关键字必须有构造器
    //2.用来初始化值
    public Person() {
        this.name = "1111";
    }
    //有参构造:一旦定义了有参构造,无参构造必须显示定义,否则会报变异错误

    public Person(String name) {
        this.name = name;

    }
    //alt+insert自动生成

1.6 封装

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


/**
 * 1.提高安全性,保护数据
 * 2.隐藏代码 的实现细节
 * 3.统一接口
 * 4.系统可维护增加
 */
public class Student {
    //属性私有
    //名字
    private String name;
    //学号
    private int id;
    //性别
    private char sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

1.7 继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

  • extends的意思是“扩展”。子类是父类的扩展。

  • JAVA中类只有单继承,没有多继承!

  • 继承是类和类之间的一种关系。除此之外类和类之间的关系还有依赖、组合、聚合等.

  • 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。

  • 子类和父类之间,从意义上讲应该具有"is a"的关系.

  • 子类会继承父类的所有域,只是私有域无法访问与使用

  • object类所有类的父类

  • super调用父类的构造方法,必须在构造方法的第一个

    1. 必须出现在子类的方法或者构造方法中
    2. 和this不能同时调用构造方法
    3. 只能在继承条件下才可以使用
  • this本身调用者这个对象

    • 没有继承也可以使用
  • !声明子类时默认先调用父类无参构造(隐藏代码super();同时该代码必须在构造器的第一行)

  • !父类没有无参构造,子类无参构造会报错

//调用父类无参构造
public class Person {
    String name;
    char gender;
}
 
 
public class Student extends Person {
//  super ();  //编译错误,必须位于子类构造方法的第一句
    double score;
    Student(double score){
        super();  //编译器默认会自动加上
        this.score = score;
        super.name = "Tom";
    }
}
//调用父类有参构造
public class Person {
    String name;
    char gender;
    Person(String name,char gender){
        this.name = name;
        this.gender = gender;
    }
}
 
 
 
public class Student extends Person {
//  super ();  //编译错误,必须位于子类构造方法的第一句
    double score;
    Student(String name,char gender,double score){
//      super();  //编译错误,父类中没有无参构造
        super(name,gender);  //调用父类有参构造
        this.score = score;
        super.name = "Tom";
    }
}
  • 方法重写

    1. 需要有继承关系,子类重写父类方法
    2. 必须是非静态,参数列表相同
    3. 修饰符只能扩大不能缩小.public>protected>default>private
    4. 抛出的一异常范围可以缩小,不能扩大.
    5. 重写都是方法重写和属性没有关系
    • 为什么需要重写:
      • 父类的功能,子类不一定需要,或者不一定满足!
    • 不能重写的方法种类
      • static方法,属于类不属于对象
      • final常量
      • private私有

1.8 多态

  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式.
  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
  • 多态存在的条件
    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意:多态是方法的多态,属性没有多态性。
  • X instanceof Y
    • 存在父子关系时编译通过
    public static void main(String[] args) {
        //Object >String
        //Object>Person>Teacher
        //Object>Person>Student
        Object obj = new Student();
        System.out.println(obj instanceof  Student);//true
        System.out.println(obj instanceof  Person);//true
        System.out.println(obj instanceof  Teacher);//false
        System.out.println(obj instanceof  Object);//true
        System.out.println(obj instanceof  String);//false

        System.out.println("------------------");
        Person obj1=new Student();
        System.out.println(obj1 instanceof  Student);//true
        System.out.println(obj1 instanceof  Person);//true
        System.out.println(obj1 instanceof  Teacher);//false
        System.out.println(obj1 instanceof  Object);//true
//        System.out.println(obj1 instanceof  String);//编译错误
        System.out.println("-------------------");
        Student obj2=new Student();
        System.out.println(obj2 instanceof  Student);//true
        System.out.println(obj2 instanceof  Person);//true
//        System.out.println(obj2 instanceof  Teacher);//编译错误
        System.out.println(obj2 instanceof  Object);//true
//        System.out.println(obj2 instanceof  String);//编译错误

    }
  • 向上转型

    1. 一个子类的对象可以向上转型为父类的类型。即定义父类型的引用可以指向子类的对象
    2. 一般情况下父类可以引用子类对象即向上转型Father father=new son();(因为子类对象中有父类所有的域);而子类不能引用父类对象Son son=new Fahter();(因为父类对象可能没有子类的所有域)
    3. 父类引用指向子类,方法的调用之和左边的数据类型相关

    B b = new A();

    b.test();//B

    1. !!!静态方法和非静态方法差别很大.静态方法是类的方法,而非静态方法是对象的方法.有static时,调用的b应该调用了B类的方法(该方法为static),当方法不为静态时b应该调用new声明出来的对象的方法A

    B b = new A();

    b.test();//A

  • 通过强制类型转换实现子类实例化为父类编译通过但执行时会报错

java.lang.ClassCastException

Son son=new Son();
Father father=new Father();
son=(Son)father;
  • Son instanceof Father->true;Fahter instanceof Son->false

  • 当父类引用一个子类对象时,不能直接调用子类中特有的域,而需要强制类型转换恢复为子类才能调用

public class castClass{
    public static void main(String[] argv){
        A as[]=new A[2];
        as[0]=new A();
        as[1]=new B();
        ((B)as[1]).getB();
    }
}

class A{
    int a;
    public int getA(){
        return a;
    }
}


class B extends A{
    int b;
    @Override
    public int getA(){
        return 1;
    }
    public int getB(){
        return b;
    }
}

1.9 static

  • 静态代码块在类加载时加载
  • 匿名代码块在静态代码加载后加载
  • 构造方法在类声明后加载
public class Teacher extends Person {
    {
        System.out.println("匿名代码块");
    }
    static {
        System.out.println("静态代码块");
    }
    public Teacher() {
        System.out.println("构造方法");
    }
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        System.out.println("----------");
        Teacher teacher1 = new Teacher();
        /*
        静态代码块
        匿名代码块
        构造方法
        ----------
        匿名代码块
        构造方法
        */
    }

1.10 抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是|抽象方法;如果
    修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法但是有抽象方法的类-定要声明为抽象类。
  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
public abstract class Action {
    //约束有人帮我们实现
    //abstract 抽象方法,只有方法名字没有方法实现
    public abstract void doSomething();

    //不能new抽象类,只能靠子类实现:约束!

    //抽象类可以写普通方法
    //抽象方法必须在抽象类中
    public  void hello(){

    }
    //思考题:抽象类构造器问题:
    //子类在调用父类时无论自己有没有构造方法都会先去执行父类无参的函数。
    //抽象类存在意义 :
    //提高开发效率提高可扩展性
}

1.11 接口

  • 普通类:只有具体实现

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

  • 接口:只有规范!无法写方法.约束和实现分离:面向接口编程可以允许多继承

  • interface

  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能.."的思想。如果你是天使,
    则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。

  • 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

  • 00的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象
    能力的语言(比如c++、 java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

  • 默认方法为public abstract

  • 默认常量为public static final;

  • 接口没有构造方法

二. 异常

2.1 什么是异常

  • 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。
  • 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
  • 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
  • 异常发生在程序运行期间,它影响了正常的程序执行流程。

2.2 异常简单分类

  • 要理解Java异常处理是如何工作的,你需要掌握以下种类型的异常:

  • 异常处理框架

    • Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
    • 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception.
  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

  • 运行时异常:运行时异常是可能被程序员避免的异常。 与检查性异常相反,运行时异常可以在编译时被忽略。

    • ArrayIndexOutOfBoundsException (数组下标越界)
    • NullPointerException (空指针异常)
    • ArithmeticException (算术异常)
    • MissingResourceException (丢失资源)
    • ClassNotFoundException (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
  • 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时, 一个错误就发生了,它们在编译也检查不到的。

    • Error类对象由Java虑拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
    • Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM) 一般会选择线程终止;
    • 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError) .链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
  • Error和Exception的区别: Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM) 一般会选择终止线程; Exception通常情况 下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

    public static void main(String[] args) {
        int a=1;
        int b=0;
        //ctrl alt t
        //假设要不或多个异常,需要从小到大
        try {

            //主动抛出异常一般在方法中使用
            if (b==0){
                throw new ArithmeticException();
            }
            System.out.println(a/b);
        } catch (Exception e) {//想要捕获的异常类型
            System.out.println("被除数不能为0");
            e.printStackTrace();
        }finally {
            System.out.println("结束");
        }

    }

2.3 自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定
    义异常。用户自定义异常类,只需继承Exception类即可。
  • 在程序中使用自定义异常类,大体可分为以下几个步骤:
    1. 创建自定义异常类。
    2. 在方法中通过throw关键字抛出异常对象。
    3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理; 否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
    4. 在出现异常方法的调用者中捕获并处理异常。
public class MyException extends Exception{
    private int detail;

    public MyException(int a) {

        this.detail = a;
    }
    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

public class Test2 {
    static void test(int a)throws MyException{
        System.out.println("传递的参数"+a);
        if (a>10){
            throw new MyException(a);//抛出
        }
        System.out.println("OK");

    }
    public static void main(String[] args) {
        try {
            test(11);
        } catch (MyException e) {
            e.printStackTrace();
            System.out.println("MyExcetion=>"+e);
        } finally {
        }
    }
}
  • 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加一个catch (Exception) 来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源
posted on 2020-10-01 19:03  桌角是小黑  阅读(143)  评论(0)    收藏  举报