• JAVA学习day04


    前言

    昨日休整一天,今日如梦初醒甚是惭愧,下定决心努力学习,奋勇向前!

    一、多态的理解

    理解

    多态解释视频

    目前理解为多态主要靠重载和重写实现。

    • 重载:在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

    重载就是多态!!

    • 重写:子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

    Person s1 = new Student();当s1调用方法如s1.run()时进行以下步骤:

    1. 看父类有没有run()方法,如果没有则报错(编译看左,即编译看父类)
    2. 父类有run()方法,且子类没有重写run()方法,此时调用父类的run()方法
    3. 父类有run()方法,且子类重写run()方法,此时调用子类的run()方法(运行看右,即运行看子类是否重写)
    4. 如果父类没有run()方法,而子类有run()方法,则可以通过强制类型转换将s1转换为Student类然后才能执行子类方法。

    代码

    Fu

    public class Fu {
        public void fun1(){
            System.out.println("Fu fun1");
        }
        public void fun2(){
            System.out.println("Fu fun2");
        }
    }
    

    Zi

    public class Zi extends Fu{
        @Override
        public void fun1() {
            System.out.println("Zi fun1");
        }
        public void fun3(){
            System.out.println("Zi fun3");
        }
    }
    

    Application

    public class Application {
        public static void main(String[] args) {
            //调用方法run()
            Fu obj = new Zi();
            obj.fun1();
            obj.fun2();
            ((Zi)obj).fun3();
        }
    }
    

    运行结果:
    Zi fun1
    Fu fun2
    Zi fun3
    (无法直接运行obj.fun3()必须强制转类型)

    另:三种方法不可被重写

    • static 方法,属于类,不可被重写
    • final 方法,常量
    • private 方法,私有

    二、instanceof的用法

    用法介绍

    公式

    instanceof (类型转换)引用类型,判断一个对象是什么类型。

    A a = new B();
    a instanceof X;
    

    A是父类引用,B是子类对象;

    比较流程

    1. 判断A(引用类型,即父类)和X的关系,当X为A的子类时才可进行下一步,否则编译阶段即报错。
    2. 判断B和X的关系,如果X是B的父亲或本身,则返回true;否则,如果X是B的子类或同级则返回false;

    代码

    Person

    public class Person {
        public void run(){
            System.out.println("run");
        }
    }
    

    Student

    public class Student extends Person{
        public void go(){
            System.out.println("son go");
        }
    }
    

    Applocation1

    public class Application1 {
        public static void main(String[] args) {
            //关系:        
            //Object>String
            //Object>Person>Student
            //Object>Person>Teacher
            
            //引用类型为Object时(祖宗类)
            Object object = new Student();
    
            System.out.println(object instanceof Student);
            System.out.println(object instanceof Person);
            System.out.println(object instanceof Object);
            System.out.println(object instanceof Teacher);
            System.out.println(object instanceof String);
    
            System.out.println("==============");
    
            
            //引用类型为Person时
            Person person = new Student();
    
            System.out.println(person instanceof Student);
            System.out.println(person instanceof Person);
            System.out.println(person instanceof Object);
            System.out.println(person instanceof Teacher);
            //System.out.println(person instanceof String);//编译即报错
    
            System.out.println("=============");
            
            
            //引用类型为Student时(祖宗类)
            Student student = new Student();
    
            System.out.println(student instanceof Student);
            System.out.println(student instanceof Person);
            System.out.println(student instanceof Object);
            //System.out.println(student instanceof Teacher);//编译即报错
            //System.out.println(student instanceof String);//编译即报错
    
            System.out.println("=============");
    
            //引用类型为Person指向对象为Person型时
            Person person2 = new Person();
            System.out.println(person2 instanceof Student);
            System.out.println(person2 instanceof Person);
            System.out.println(person2 instanceof Object);
            System.out.println(person2 instanceof Teacher);
        }
    }
    

    运行结果:

    true
    true
    true
    false
    false
    ============
    true
    true
    true
    false
    ============
    true
    true
    true
    ============
    false
    true
    true
    false

    三、类型转换

    规律

    1. 父引用指向子对象
    2. 子->父,向上转型
    3. 父->子,向下转型:强转
    4. 方便方法调用,减少重复代码

    代码

    父类和子类代码同上

    Application2

    public class Application2 {
        public static void main(String[] args) {
            
            //类型转换:基本类型转换 高低64 32 16 8
    
            Person obj = new Student();
            //obj.go();不能用go方法
            //需要将obj转成Student类型
            Student student = (Student) obj;
            student.go();
            //或者((Student) obj).go;
    
            //子转父可能会丢失子方法(向上转型)
            Person person = student;
            //student转person是低转高,默认转换即可,但可能会丢失方法
            //person.go();
        }
    }
    

    运行结果
    son go

    四、static详解

    • 非静态的方法可以随意调用静态方法;静态方法只能调用静态方法

    代码块

    public class Student {
        {
            System.out.println("匿名代码块");
        }
    
        static {
            System.out.println("静态代码块");
        }
        public Student(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Student s1 = new Student();
            System.out.println("_________");
            Student s2 = new Student();
    
        }
    }
    

    运行结果:
    静态代码块
    匿名代码块
    构造方法
    _________
    匿名代码块
    构造方法

    注意

    • 静态代码块只执行一次
    • 匿名代码块在构造方法前可以用来赋初始值

    对一些想法的测试

    如果不构造本类会发生什么呢?

    1. 测试多态

    public class Student {
        {
            System.out.println("匿名代码块");
        }
    
        static {
            System.out.println("静态代码块");
        }
        public Student(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Person s3 = Student();
        }
    }
    

    结果:
    静态代码块
    匿名代码块
    构造方法

    2. 测试不构造本类

    public class Student {
        {
            System.out.println("匿名代码块");
        }
    
        static {
            System.out.println("静态代码块");
        }
        public Student(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Person s4 = Person();
        }
    }
    

    结果:
    静态代码块

    总结:

    1. 多态使用子类的构造器
    2. static和类一起编译运行,只要加载此类必然且只运行一次

    静态导入别的类的静态方法

    import static java.lang.Math.random;
    
    public class Test{
        public static void main(String[] args) {
            System.out.println(random());
            //通过静态导入方法,即无需再打Math.random(),只打random()即可;
        }
    }
    

    五、抽象类

    abstract

    • 抽象类中可以有抽象方法和普通方法
    • 不能new抽象类,只能依靠子类去实现
    • 子类必须重写new方法
    • 抽象方法必须在抽象类中
    • 抽象类有构造方法(用来给子类提供,所有子类必须调用从Object开始的所有父类的构造函数)
    • 抽象类可以写静态方法
    • 提高开发效率

    六、接口

    普通:只有具体实现
    抽象类:具体实现和规范(抽象方法)都有
    接口(Interface):一组规范,不可以写方法体和静态方法,没有构造器
    接口本质是契约

    接口的所有定义都是抽象的public abstract
    接口的所有常量都是public static final

    代码

    UserService(interface)

    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(interface)

    public interface TimeService {
        void timer();
    }
    

    UserSeriviceImp1

    //实现接口的类,必须重写接口中的方法
    public class UserServiceImp1 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() {
    
        }
    }
    

    七、内部类

    类的内部再定义一个类

    代码

    Outer

    public class Outer {
        private int id=10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
    
        //如果Inner被static修饰则不能getID,因为static直接加载,除非把id也改成static
        class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
    
            //获得外部类的私有属性
            public void getID(){
                System.out.println(id);
            }
        }
    
        //局部内部类
        public void method(){
            class Inner{
                public void in(){
    
                }
            }
        }
    }
    
    //一个java类中可以有多个class类,但只能有一个public class
    class A{
        public static void main(String[] args) {
        }
    }
    
    

    Application

    public class Application {
        public static void main(String[] args) {
            //new
    
            Outer outer = new Outer();
            //通过外部类来实例化内部类
            outer.new Inner();
            Outer.Inner inner = outer.new Inner();
            inner.in();
            inner.getID();
        }
    }
    

    Test

    public class Test {
        public static void main(String[] args) {
            //匿名对象的使用,没有名字初始化类,不用将实例保存到变量中
            new Apple().eat();
    
            UserService userService = new UserService() {
    
                @Override
                public void hello() {
    
                }
            };
        }
    }
    class Apple{
        public void eat(){
            System.out.println("1");
        }
    }
    
    interface UserService{
        void hello();
    }
    

    八、异常

    什么是异常

    Exception,程序运行出现了异常;
    异常:程序运行中出现了不期而至的状况

    分类

    • 检查性异常:代表性的例子是用户错误或问题引起的异常。程序员无法预见,如打开不存在的文件,就会发生一个异常。
    • 运行时异常:可能被程序员避免的异常。运行时异常可以在编译时被忽略
    • 错误ERROR:错误不是异常是脱离程序员控制的问题。例如栈溢出,它们在编译时也检查不到。

    异常分类

    异常体系结构

    • Java把异常当作对象处理,定义java.lang.Throwable作为所有异常的超类
    • Java API中已经定义了许多异常类,分为两大类,错误Error和异常Exception。

    具体介绍

    Error

    • Error类对象由Java虚拟机抛出,大多数错误和代码编写者的操作无关。
    • Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,会出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
    • 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError),链接错误(LinkageError)。这些错误时不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数时程序运行时不允许出现的情况。

    Exception

    • Exception分支中有一个非常重要的子类RuntimeException(运行时异常)
      • ArrayIndexOutOfBoundsException(数组下标越界)
      • NullPointerException(空指针异常)
      • ArithmeticException(算数异常)
      • MissingResourceException(丢失资源)
      • ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获异常,也可以选择不处理。
    • 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
    • Error和Exception的区别:Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这些异常是,Java虚拟机(JVM)会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能地去处理这些异常。

    处理机制

    异常处理的五个关键字:try、catch、finally、throw、throws

    代码

    Test

    public class Test {
    //假设捕获多个异常,从小到大!
            try {//try监控区域
                if (b==0){
                    throw new ArithmeticException();//主动抛出异常
                }
                System.out.println(a/b);
                //new Test().a();
            }catch(Error e){
                System.out.println("Error");
            }
            catch (ArithmeticException e){//catch(想要捕获的参数类型) 捕获异常
                System.out.println("Exception");
            }catch (Throwable e){
                System.out.println("Throwable");
            }finally{
                //finally一定会被执行,善后工作
                System.out.println("finally");
            }
    
            //finally可以没有,但try和catch必须要有
            //如果是IO异常,需要关闭,来释放资源
    }
    

    第一部分总结:

    • try后面可以跟多个catch,catch应该由小到大
    • finally代码块是一定会被执行的,一般负责善后工作,如:关闭IO流

    Test

    public class Test {
        public static void main(String[] args) {
            try {
                new Test().test(1,0);
            } catch (ArithmeticException e) {
                e.printStackTrace();
            } 
        }
    
        //假设这个方法中,处理不了这个异常,方法上抛出异常
        public void test(int a,int b) throws ArithmeticException{
            if (b==0){
                throw new ArithmeticException();//主动抛出异常
            }
        }
    }
    

    第二部分总结

    • throws用在方法上,throw用在try catch内;如果有方法里解决不了的异常,就由throws,抛至上层进行处理

    Test2

    public class Test2 {
        public static void main(String[] args) {
            int a=1;
            int b=0;
    
    
            //ctrl+alt+t 快速开启环绕菜单
            //QQ占用热键,关闭QQ或用ctrl+alt+win+t可以开启
            try {
                System.out.println(a/b);
            } catch (Exception e) {
                e.printStackTrace();//打印错误的栈信息
            }finally {
    
            }
        }
    }
    

    第三部分总结

    臭QQ搞得我快捷键搞半天,ctrl+alt+t可开启环绕菜单,热键被占多按个win

    自定义异常

    用户可以自定义异常,只需继承Exception类。

    步骤:

    1. 创建自定义异常类。
    2. 在方法中通过throw关键字抛出异常对象
    3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并进行处理;否则在方法的声明中通过throws关键字知名要抛出给方法调用者的异常,继续进行下一步操作。
    4. 在出现异常方法的调用者中捕获并处理异常

    代码

    MyException(自定义的异常)

    //自定义的异常类
    public class MyException extends Exception{
    
        //传递数字>10
    
        private int detail1;
    
        public MyException(int a) {
            this.detail1 = a;
        }
        //toString异常的打印信息
        @Override
        public String toString() {
            return "MyException{" +
                    "detail1=" + detail1 +
                    '}';
        }
    }
    
    • toString就是将实例化对象转换成能输出的字符串类型,自动转换可以sout直接输出

    TestMyException测试类

    public class TestMyException {
    
        //可能存在异常的方法
    
        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) {
                System.out.println("MyException=>"+e);
            }
        }
    }
    

    完成对异常的测试,test成功捕获后抛出给主函数,主函数catch捕获到MyException后执行操作,将捕获到的异常实例e自动通过toString方法,通过sout输出。

    异常经验总结

    • 处理运行异常时,采用逻辑去合理规避同时辅助try-catch处理
    • 在多重catch块后,可以加一个catch(Exception)来处理可能被遗漏的异常
    • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
    • 尽量处理异常,切忌只是调用printStackTrace()来打印输出
    • 具体如何处理,根据不同业务和异常类型去决定
    • 尽量添加finally语句去释放占用资源
  • 相关阅读:
    Object上的静态方法
    【php实现数据结构】单向链表
    图片上传方案详解
    新手必踩坑之display: inline-block
    前端算法题:找出数组中第k大的数字出现多少次
    this的五种指法
    通过java反射实现的excel数据导出
    算法系列-动态规划(4):买卖股票的最佳时机
    算法系列-动态规划(3):找零钱、走方格问题
    数据库仓库系列:(一)什么是数据仓库,为什么要数据仓库
  • 原文地址:https://www.cnblogs.com/ebym/p/15663830.html
Copyright © 2020-2023  润新知