一、多态

1. 概述

  • 理解:多态可以理解为事物存在的多种体(表)现形态。

    • 例如:

      • 动物中的猫和狗。
      • 猫这个对象对应的是猫类型,例如:猫 x = new 猫();
      • 同时猫也是动物中的一种,也可以把猫称为动物,例如:动物 y = new 猫();
      • 动物就是猫和狗这些具体事物中抽取出来的父类型,父类型的引用指向了子类对象。
  • 体现
    1. 父类的引用指向了子类的对象。
    2. 父类的引用也可以接收自己子类的对象。
      • 例如:Animal a = new Cat();

        • 父类型 a 的引用指向了子类的对象。
  • 前提
    1. 类与类之间必须有关系,要么是继承,要么是实现。
    2. 存在重写(覆盖),父类中有方法被子类重写(覆盖)。

2. 利与弊

  • 利:提高了程序的可扩展性和后期的可维护性。

  • 弊:只能使用父类中的引用去访问父类中的成员。

    • 使用了多态,父类型的引用在使用功能时,不能直接调用子类中特有的方法。

      • 例如:Animal a = new Cat();//多态的体现

        • 假设子类 Cat 中有抓老鼠的特有功能,父类型 a 就不能直接调用该功能,可以理解为 Cat 类型向上转型,提升了。
        • 父类的引用想要调用子类 Cat 中特有的方法,就要将父类的引用强制转换成子类的类型,向下转型。例如:Cat c = (Cat)a;
      • 注:
        • 如果父类可以创建对象的话,例如:Animal a = new Animal(); 就不能进行向下转型了,Cat c = (Cat)a; 这样编写代码在编译时会报错,不要出现将父类对象转换成子类类型。
        • 多态转换的是父类引用指向了自己子类的对象时,该引用可以被提升,也可以被强制转换,多态始终都是子类对象在做变化的。
  • 例如:

3. 特点

1. 成员变量

  • 无论编译还是运行时期,都参考左边(引用变量)所属的类。

    • 例如:多态中父类引用调用成员变量时,如果父类和子类有同名的成员变量,被调用的则是父类中的成员变量。

2. 非静态成员函数

  • 编译时期:参考引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,编译失败。

    • 例如:a.catchMouse();//编译报错,这种情况只能通过强制转换,向下转型后才可以使用子类中特有的功能。
  • 运行时期:参考对象所属的类中是否有调用的方法,如果父类中有一个非抽象方法,子类继承后将其重写(覆盖)了,多态运行时,父类的引用调用同名函数时,运行的是父类中的方法。
  • 总而言之:成员函数在多态调用时,编译看左边,运行看右边。

3. 静态成员函数

  • 无论编译还是运行时期,都参考左边,就是父类的引用在调用同名静态成员函数时,调用的是父类中的静态成员函数。

    • 原因:

      • 当类一被加载时,静态成员函数随类绑定在内存中,不需要创建对象,可以通过类名直接调用静态成员函数,并且父类中的静态成员函数一般是不被重写(覆盖)的。

      • 类在方法区中的分配:静态方法区和非静态方法区(关键字 super 和 this 在非静态方法区中)。

4. 应用

  1. 定义工具类,将共同行为封装在同一个类中。
  2. 对类型进行抽取(多态的产生)。
  3. 操作同一个父类型,对其中的子类型均可进行操作。
    • 例如:

二、内部类

1. 概述

  • 概述:将一个类定义在另一个类里面,定义在类里面的那个类称为内部类(内置类、嵌套类)。
  • 理解:当描述事物时,事物的内部还存在事物,事物内的事物使用内部类来描述,印务内部事物在使用外部事物的内容。
    • 例如:定义一个人的类,手、脚、心脏等等都属于人,这些又各自有自己的功能描述,这时候就可以在人这个描述类中,定义一些描述手、脚、心脏的类,也就是定义一些内部类。
  • 编译现象:编译 Java 文件时,如果类中有内部类,生成的 class 文件中会含有 Test$1.class 等等这样的文件,编译器会把内部类翻译为用 $(美元符号)分隔外部类名和内部类名的类文件,这是内部类的一种编译现象。

2. 访问规则

  1. 外部类要访问内部类,必须建立内部类的对象。
  2. 内部类可以直接访问外部类中的成员(包括私有成员)。
    • 原因:因为内部类中持有外部类的引用。
    • 格式:外部类名.this

3. 访问格式

  1. 内部类定义在外部类的成员位置,而且非私有时,可以在外部的其它类中直接建立内部类对象。

    • 格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象;

      • 例如:Outer.Inner in = new Outer().new Inner();
    • 内部类定义在外部类的成员位置时,可以被成员修饰符所修饰。
      • 例如:

        • private:内部类在外部类中进行封装。
        • static:内部类有局部 statci 的特性,内部类被 static 修饰后,只能访问外部类中的 static 成员。
          • 外部的其它类访问 static 内部类中静态成员的格式:外部类名.内部类名.方法名();

            • 例如:Outer.Inner.function();
          • 外部的其它类访问 static 内部类中非静态成员的格式:new 外部类名.内部类名().方法名();
            • 例如:new Outer.Inner().function();
    • 注:
      1. 内部类中定义了静态成员时,该内部类必须是 static 的。
      2. 外部类中的静态方法访问内部类时,内部类也必须是 static 的。
      3. 实际开发中,内部类一般定义为 private,很少定义为 public 的。
  2. 内部类定义在局部位置
    1. 不可被成员修饰符所修饰,作用域限定在声明这个局部内部类的代码块中。

      • 例如:public、private、static 等修饰符。
    2. 可以直接访问外部类中的成员,还持有外部类的引用。
      • 注:内部类不可以访问所在局部中的非最终变量,只能访问被 final 修饰的局部变量。

      • 例如:

        • 分析:上述代码中的打印结果为 7、8,会改变,并没有因为被 final 所修饰就无法改变,原因是因为类调用方法结束后,被 final 修饰的变量已经从桟内存中消失,类再次调用方法时,已经是另一个变量了,所以可以重新传值。

4. 匿名内部类

  • 匿名内部类就是内部类的简写格式,匿名内部类其实就是一个匿名子类对象,可以理解为带内容的对象。

  • 格式:new 父类或接口(){定义子类的内容}

  • 定义匿名内部类的前提:

    • 匿名内部类必须是继承一个类或者实现接口。

      • 特殊情况:所有的类都有一个父类 Object,定义时也可用 Object。
  • 利与弊:

    • 利:简化书写。
    • 弊:
      1. 不能做强转的动作。
      2. 不能直接调用自己的特有方法。
      3. 如果继承的父类或接口中方法很多时,使用匿名内部类的可阅读性会非常差,调用也非常麻烦,因此匿名内部类中定义的方法一般不超过3个。
  • 例如:

三、异常

1. 概述

  • 异常是 Java 中的重要机制,使用面向对象的思想进行了封装,通常使用的是异常类。异常类中描述的就是程序中可能出现的错误或者问题。
  • 程序在运行时出现不正常的情况称为异常。
  • 由来:异常问题也是现实生活中一个具体的事物,可以通过 Java 中类的形式进行描述,并封装成对象,异常类就是 Java 对不正常的情况进行描述后的对象体现。
  • 程序中可能出现的错误或者问题:
    1. 用户输入错误导致的异常:非法参数、不按正常的使用程序等。
    2. 设备硬件等发生的错误的异常:硬盘损坏等。
    3. 物理限制的异常:存储空间不足、SDCard不存在等。
    4. 代码错误的异常:程序编写的方法不正确、返回错误的参数等。

2. 体系

异常问题的划分方式

  1. 严重的异常问题。

    • 严重的异常问题,Java 通过 Error 类进行描述,对于 Error 类一般不编写针对性的代码进行处理。
  2. 非严重的异常问题。
    • 非严重的异常问题,Java 通过 Exception 类进行描述,对于 Exception 类可以使用针对性的代码进行处理。

        注:无论是 Error 或 Exception 都具有一些共性内容,例如:不正常情况的相关信息、引发异常的原因等。

体系

  • Throwable

    • Error//出现重大异常问题。例如:运行的类不存在或者内存溢出等。
    • Exception//运行时出现的异常情况。
      • RuntimeException//特殊的异常类,Exception 的子类,抛出时不需要做声明。
  • 注:Error 和 Exception 的子类名称都是以父类名做为后缀。

特点

  1. 异常体系中所有类以及建立的对象都具备可抛性;
  2. 可以被 throw 和 throws 关键字所修饰操作;
  3. 只有异常体系才具备这个特点。

3. 分类

编译时异常

  • 异常在编译时,如果没有做任何处理(没有抛也没有 try),编译失败。
  • 异常被标识,代表可以被处理。

运行时异常

  • 编译时不需要处理,编译器不检查。
  • 异常发生时,Java 建议不处理,让程序停止。
  • 需要对代码进行修正。(例如:RuntimeException 以及 RuntimeException 的子类)

4. 处理

  • Java 中提供了特有的语句进行处理:

      try{
    需要检测的语句;
    }catch(异常类 变量){
    处理异常的语句(方式);
    }finally{
    一定要执行的语句;
    }
    • 这些特有语句的处理方式有三种结合情况:

        1.
      try{
      需要检测的语句;
      }catch(异常类 变量){
      处理异常的语句(方式);
      }
      2.
      try{
      需要检测的语句;
      }finally{
      一定要执行的语句;
      }
      3.
      try{
      需要检测的语句;
      }catch(异常类 变量){
      处理异常的语句(方式);
      }finally{
      一定要执行的语句;
      }
    • 注:

      1. finally 中定义的一般是关闭资源的代码,资源使用完后必须释放。
      2. 如果存在一些功能是必须执行的,可以使用 try{}finally{} 的方式,将必须执行的语句放在 finally 代码块中。
      3. finally 只有一种情况是不会执行的,在进入 finally 之前就先执行了 System.exit(0); 时,已经是退出了程序,finally 就不会执行的。
  • throw 和 throws 的用法:

    • throw 定义在函数内,用于抛出异常对象。
    • throws 定义在函数上,用于抛出异常类,可以抛出多个对象,使用 , 隔开即可。
      • 当函数的内容有 throw 抛出异常对象,但没 try 处理时,必须在函数上声明,否则会导致编译失败。
    • 注:RuntimeException 除外,函数内如果抛出的是 RuntimeException 异常,函数上不需要声明。
  • 抛出信息的处理:

    • 函数中出现了 throw 抛出异常对象时,要么是在函数内部进行 try 的处理,要么是在函数上声明,让函数的调用者去处理。

    • 对于捕获到的异常对象常见的操作方法:

        getMessage();//获取异常信息,返回字符串
      toString();//获取异常类名和异常信息,返回字符串
      printStackTrace();//获取异常类名、异常信息以及异常在程序中出现的位置,返回值 void,JVM 默认的异常处理机制中,就是调用 PrintStackTrace() 方法来打印异常的堆栈跟踪信息
      printStackTrace(PrintStream s);//将异常内容保存在日志文件中

5. 自定义

  • 对于一些特有的问题,这些特有的问题没有被 Java 所描述封装为对象,对于这些特有的问题,可以按照 Java 的面向对象思想将问题进行自定义的异常封装,这就是自定义异常。

    • 自定义异常类继承 Exception 或 RuntimeException

      1. 让自定义异常类具备可抛性。
      2. 让自定义异常类具备操作异常的共性方法。
    • 如何自定义异常信息?
      • 自定义异常信息可以使用父类已定义好的功能,异常信息传递给父类的构造函数,由于父类中已经把异常信息的操作都完成了,子类只需在构造函数中,通过 super 语句将异常信息传递给父类,就可以通过 getMessage() 方法获取自定义的异常信息了。

      • 例如:

        • 说明:定义异常时,如果异常的发生,会导致无法继续进行运算,则让自定义异常类继承 RuntimeException。
      • 注意:自定义异常必须是自定义异常类有继承关系,一般继承 Exception。

        • 自定义异常类继承 Exception 的原因?

          • 异常体系的特点就是异常类和异常对象都具备可抛性,这个可抛性是 Throwable 体系中独有的特点,只有这个体系中的类和对象才可以被 throw 和 throws 所操作。

6. 好处与原则

好处

  1. 将问题进行封装。
  2. 将正常流程的代码和问题处理的代码分离,便于阅读。

原则

  1. 处理方式:try 或 throws。
  2. 调用到抛出异常的功能时,需要对所有抛出的异常进行处理,一个 try 可以对应多个 catch。
  3. 多个 catch 时,父类的 catch 需放到最后面,否则编译会报错,因为执行了父类的 catch 语句后,其余的 catch 语句将无法执行到。
  4. catch 中需要定义针对性的处理方式,一般不建议简单的定义 PrintStackTrace 输出语句,也不建议不做处理。
    1. 如果捕获的异常在本功能内处理不了的话,可继续在 catch 中抛出。

      • 例如:

    2. 如果捕获的异常在本功能内处理不了的话,但并不属于本功能出现的异常,可以将异常转换后再抛出。

    3. 如果捕获的异常在本功能内可以处理的话,但需要将异常产生后和本功能相关的问题提供出去给调用者,可以将异常转换后再抛出。

      • 例如:

7. 注意事项

  1. 异常问题在内部被解决就无需声明。
  2. catch 是用于处理异常,如果没有 catch,就代表异常问题没有被处理,该异常如果是检测时异常,就必须声明。
  3. 子父类重写(覆盖)时:
    1. 子类抛出的异常必须是父类异常的子类或者子集。
    2. 父类或接口没有异常抛出时,子类重写(覆盖)出现异常时,只能 try,不能抛。
      • 例如:

四、包(package)

1. 概述

  • Java 中将 package 称为包,相当于文件夹,包里面一般存放的是类文件。由于在编写程序时,难免存在类名相同的情况,为了便于对类进行分类管理,Java 便提供了包,以包的形式存放不同的类,在不同的包中可以有相同的类名,只需在调用时连同包名一起即可。

    • 包也是一种封装的形式。

2. 作用

  1. 为了避免多个类重名的情况,出现多个相同名字的类时,可通过包将其区分,避免冲突。
  2. 对类文件进行分类管理,可以将相关的类放在同个包中。
  3. 包的出现将 Java 的源文件和类文件分离。
  4. 给类提供了多层命名空间。
    • 例如:

      • a 包中的 Demo.class 文件,如果要创建 Demo 对象,在使用时需加上 a.
      • a.Demo demo = new a.Demo();

3. 规则

  1. 包必须写在程序的第一行,先有包,才知道类文件的存放位置。
  2. 类的全称:包.类名。
  3. 编译定义了包的程序文件时,在编译时需指定包的存放目录。
    • 例如:javac -d e:\Demo\mypack 类名.java

4. 包与包之间的访问

  1. 被访问的包里类的权限必须是 public。
  2. 访问其它包中的类时,需定义类的全称:包名.类名。
  3. 包如果不在当前路径的话,需使用 classpath 设置环境变量,为 JVM 指明路径。
  4. 类中的成员权限必须是 public 或 protected。
    • 类公有后,被访问的成员也要公有才能被访问。

    • protected 是为子类提供的一种权限。

    • 同个包中,protected 只做用为覆盖。

    • 不同包中的子类可以直接访问父类中被 protected 权限修饰符所修饰的成员。

    • 四种权限修饰符:

      • 注:由于被 public 所修饰的类名必须与 java 文件名相同,因此在一个 .java 文件中,不允许出现两个或以上的公有类或接口。

5. 导入(import)

  • 一个程序文件中只有一个 package,可以有多个 import,import 导入的是包中的类,不导入包中的包。
  • import 可以简化类名,在调用其它包中的类时,需要写类的全称,就是连同包名一起书写,当类存在多层包中时,使用 import 导入后,使用该类时,可以不加包名。
    • 例如:

      • a.b.c.pack.Demo
      • 导入的格式为 import a.b.c.pack.Demo;
      • 使用该类时,可直接写 Demo
  • 注意事项:
    1. 导入不同包中有想同类时,必须写类的全称以做区分,否则会报错。
    2. 定义包名不能重复,可以使用 url 来定义,url 是唯一的。
      • 例如:package com.java.Demo
    3. 导入包时,如果包中有很多类,可以使用通配符 * 代替包中所有的类,但不建议使用通配符 *,因为这样会将不需要使用的类一同导入,会占用内存空间,编写程序时,需要使用包里的哪些类就导入哪些类。

6. jar 包

  • 类越来越多时,可以使用包类封装。包越来越多时,可以将包进行压缩,Java 中通过 jar 工具对包进行压缩,压缩后的的后缀名为 jar。
  • jar.exe 工具的常用命令:
    • 创建 jar 包

      • jar -cvf mypack.jar mypack
    • 查看 jar 包
      • jar -tvf mypack.jar
    • 解压缩
      • jar -xvf mypack.jar
    • 自定义 jar 包的清单文件
      • jar -cvfm mypack.jar mypack.mf mypack
  • 好处:
    1. 数据库、驱动、SSH框架等都是以 jar 包体现的。
    2. 将多个包压缩为一个 jar 包文件,便于项目携带。
    3. 便于使用,只要在 classpath 设置 jar 包的路径,即可执行 jar 包中的 java 程序。

Java 多态、内部类、异常、包的更多相关文章

  1. Java基础内部类、包的声名、访问修饰符、代码块整理

    内部类 14.1内部类概念 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类.其他类也称为外部类. 内部类分为成员内部类与局部内部类. 我们定义内部类时,就 ...

  2. Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

    Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字 一丶Java中包的机制 首先包其实就是个文件夹.作用就是管理类. Java中每次定义一个类的时候.通过Java编译之后.都会生 ...

  3. Java面向对象(static、final、匿名对象、内部类、包、修饰符、代码块)

    面向对象 今日内容介绍 u final u static u 匿名对象 u 内部类 u 包的声明与访问 u 四种访问修饰符 u 代码块 第1章 final关键字 1.1 final的概念 继承的出现提 ...

  4. 夯实Java基础系列10:深入理解Java中的异常体系

    目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...

  5. Java面向对象㈢ -- 内部类

    内部类必须要依赖于继承或实现一个接口.内部类可以实现Java多继承,内部类访问外表类的局部变量或参数时,则该局部变量或参数必须被final修饰.内部类不能包含有static的变量和方法,原因是因为内部 ...

  6. C++和java多态的区别

    C++和java多态的区别 分类: Java2015-06-04 21:38 2人阅读 评论(0) 收藏 举报  转载自:http://www.cnblogs.com/plmnko/archive ...

  7. 深入理解Java多态机制

    从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...

  8. 关于java中的异常问题 1

    1.首先参考一下关于java异常处理方面的知识 查看博客http://lavasoft.blog.51cto.com/62575/18920/ 这里介绍的很好,下面从中学习到一些东西,摘抄如下: 1. ...

  9. java的访问控制(包、访问修饰符、修饰符)

    一.     java的类包 编写好一个源程序后,首先要执行javac命令进行编译源文件,并生成与源文件同名后缀为“.class”的字节码文件(类文件),该类文件与源文件默认在同一个目录中.该类文件是 ...

随机推荐

  1. 201521123026 《Java程序设计》第一周学习总结

    1. 本章学习总结 1.简要了解JAVA的发展史以及其特点(面向对象.跨平台性,健壮性,安全性,可移植性,多线程性,动态性等) 2.认识JAVA三大平台(Java SE,Java EE,JavaME) ...

  2. 201521123039《Java程序设计》第十三周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 下面是IP地 ...

  3. 201521123122 《java程序设计》第十四周学习总结

    ## 201521123122 <java程序设计>第十四周实验总结 ## 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. M ...

  4. php数据库连接及简单操作

    数据库改密码:mysql的控制台mysql console 中文乱码解决方法:原因编码格式不一致1.建立数据库的时候,字符集选择utf-82.修改mysql的配置:在[mysqld]模块下面添加cha ...

  5. Rigidbody(刚体) and Collider(碰撞器)

    关于刚体Rigidbody,手册上是这么描述的: Control of an object's position through physics simulation. 通过物理模拟控制一个物体的位置 ...

  6. (转)Unity3D 之插值计算

    在unity3D中经常用线性插值函数Lerp()来在两者之间插值,两者之间可以是两个材质之间.两个向量之间.两个浮点数之间.两个颜色之间,其函数原型如下: Material.Lerp 插值 funct ...

  7. Zabbix通过SNMP监控多核CPU使用率时, 计算CPU平均使用率

    环境:没有Agent,只能通过SNMP监控时,需要获取多核CPU的平均使用率. ZABBIX的使用SNMP监控CPU使用率时,由于设备都是多核CPU,监控的都是单独某一核心的使用率,但单独某一核使用率 ...

  8. Matlab入门学习(矩阵、函数、绘图的基本使用)

    一.矩阵 1.定义和简单使用(一般的编程语言,数组下标都是从0开始的,但是MATLAB是从1开始的) >> a=[ ; ; ] a = >> b=[ ; ; ]; >&g ...

  9. 翻译 | 一行 JavaScript 代码的逆向工程

    原文地址:Reverse Engineering One Line of JavaScript 原文作者:Alex Kras 译者:李波 校对者:冬青.小萝卜 几个月前,我看到一个邮件问:有没有人可以 ...

  10. 【个人笔记】《知了堂》node.js简介及创建应用

    Node.js是什么? Node.js是建立在谷歌Chrome的JavaScript引擎(V8引擎)的Web应用程序框架.Node.js自带运行时环境可在Javascript脚本的基础上可以解释和执行 ...