java 之扩展概念
扩展概念是对面向对象思想中的封装性、继承性以及多态性在 Java 中的应用的进一步阐述。
一、Object 类
Java 中引用数据类型包括类、接口、数组,如何进行统一管理呢?
Object 类是所有引用数据类型的父类,通过对象的多态性,实现各种类型的管理。对于接口,比较特殊。
为什么 Object 类中有一个无参构造方法?
Object 源码中没有显式展示无参构造,但是系统编译时会自动生成。对于 Object 类的无参构造,主要是在子类进行实例化时,默认首先执行 Object 父类的无参构造,满足继承性特点。
对于 Object 类,需要注意以下方法,这些方法是在 Java 类开发中经常覆写的方法。
注意:
1、开发的代码不重要,主要是怎么分析,怎么解构问题,即解决问题的能力;
2、对于对象比较,如果是集合结构中进行查找和删除指定内容,建议覆写 Object 类的 hashCode()和 equals()方法来实现,如果是进行集合排序,则可以实现 Comparable 接口,通过 compareTo()方法实现。当然,查找和删除指定内容也可以通过 Comparable 接口实现,但是因为所有类都是 Object 的子类,这样更加方便一些。
3、对于覆写垃圾回收处理的 finalize()方法,需要注意引用强弱的问题,尤其强引用和软引用。
二、匿名内部类
为了能够临时使用接口和抽象类,又不用定义子类为长期使用,可以使用匿名内部类解决。
匿名内部类是基于接口或者抽象类而应用的。通常而言,一个 Java 文件,只是适合编写一个类,那么,对于接口和抽象类而言,其子类就建议不要写在该文件中,或者,直接使用匿名内部类的方式使用接口或者抽象类,这样可以方便快速开发。
匿名内部类可以帮助用户减少类的开发。
也可以理解匿名内部类为匿名对象。
代码示例如下:
三、包装类
在 Java 面向对象思想中,一切皆对象。但是,因为基本数据类型并非对象,因此,为了满足面向对象思想,故设计出了包装类。
包装类的设计思想便是设计的类中拥有对应基本数据类型的属性,用于存储基本数据类型数据。
包装类分为以下两种:
对象型包装类(Object 直接子类):Character、Boolean
数值型包装类(Number 直接子类):Byte、Short、Integer、Long、Float、Double
Java1.5 之前包装类包含以下操作,即装箱和拆箱。但是在 jdk1.5 新特性之后,Java 提供自动装箱和自动拆箱,并能够利用包装类的对象进行数学计算。这样的方式,大大提高了数据类型的选择,基本数据类型也能够像引用数据类型进行操作,方便了开发。
增加了自动装箱和自动拆箱,但是对于数据类型的存储方式,并没有改变,基本数据类型存储在栈空间。
代码:
注意:包装类一般不使用构造方法装箱,对象值比较实用 equals。标红地方会有结果不同,类似于字符串直接赋值和构造方法赋值的原理。
代码:
注意:对于 Object 类与包装类之间的转换,jdk1.8 新特性之后可以直接将 obj 向下转型使用 int,而在 jdk1.8 之前,jdk1.5 之后,则只能使用 Integer。
四、包
包也就是程序的目录,可以利用包将同一文件下不同类进行拆分,根据要求放置于不同的目录下。定义包可以使用关键字 package。
对于包,可以使用命令实现,不要进行手工建包目录。当然,实际上,现在已经不可能再使用这样的方式进行开发了,因为都是依赖于开发工具。
打包编译:
在 Java 大型项目中,会出现多个文件互相访问的情况,在编译打包时,提供了通配的方式,即 javac -d . *.java
javac -d . 类名称.java
“-d”:生成目录,根据 package 定义生成;
“.”:设置保存的路径,“.”表示当前文件保存的目录。
解释程序:
不需要进入到目录里解释,直接在包当前目录输入完整路径名称(包.类)
java 包路径.类
在 Java 开发中,需要使用不同包的类,故使用 import 导包完成。但是需要导入相同目录下的多个包,则可以使用 import 包目录.*方式完成所有包的导入。
jar 文件是存储一系列字节码的压缩文件,以包为单位。使用以下指令对包进行压缩:
jar -cvf 文件名.jar 开发包
生成好后的 jar 文件无法直接使用,通过配置 CLASSPATH 属性即可进行类的加载。这也是为什么大型项目第三方开发包文件使用频繁方便的原因。或者使用 java -cp a.jar com.fys.A 指令实现,其中-cp 表示将指定类加载路径。
五、访问控制权限
为了对类的内部结构进行保护,面向对象提出了封装性的思想。Java 中的属性使用关键字 private 修饰,就是这一特性的最好作证。但是对于内部结构的保护,也有相应的范围,不是所有其他的类不能访问自己的内部结构。为了解决这一个问题,Java 提供了访问控制权限。
访问控制权限与封装性是息息相关的,程序的封装性由访问控制权限中 private、default、protected 定义。访问控制权限范围如下所示:
实际开发中很少用到 protected 进行权限控制,在 Java 的 Object 类中的 finalize 方法。这里谈的实际开发指的是专门针对于业务的开发,但是,一旦接触到框架,任何知识,就没有常不常用之说了,这是需要注意的。
@Deprecated(since="9")
protected void finalize()throws Throwable
六、异常
异常就是程序指令执行过程出现中断,出现异常,则程序终端执行。为了保证出现异常之后程序能够继续执行,应该对可能出现异常的代码进行处理操作。
异常的处理可以使用 try...catch...finally 语法进行,其结构有 try...catch、try...finally 和 try...catch...finally。
在 Java 中提供了许多定义好的异常处理类,其中这些异常处理类都是 java.lang.Throwable 的子类,并且分为 java.lang.Error 和 java.lang.Exception。
Error:Java 虚拟机错误,程序指令执行前就出现的问题,无法捕获。但是,在实际的开发中,玖富品质商城项目曾经在程序捕获过 Error。
Exception:程序执行过程中出现的异常,能够被捕获处理,若不处理,则会由 JVM 进行处理。
RuntimeException 类及其子类异常,开发中可以根据需要决定是否进行异常捕获处理,不强制要求用户进行异常处理。但是,如果用户没有进行异常处理,当异常出现时,则会交由 JVM 默认处理。
RuntimeException 的常见子类有:NullPointerException、ClassCastExcetpion、ArithmeticException、IllegalThreadStateException。
在实际的开发之中,现有阶段提供的异常不够,会需要开发一些自定义的异常。自定义的异常通过继承 Exception 或者 RuntimeException 类实现。对于自定义的异常,往往是达到架构设计时才会需要。
对于异常处理的流程见下图:
throws 关键字,定义在方法名之后,表示方法中出现异常时,异常交由方法被调用处处理。一旦方法使用了 throws 关键字,调用方法处不管程序中是否出现异常,都需要使用 try...catch 进行捕获。但是如果在主方法上使用 throws,那么,异常则会交由 Java 虚拟机进行处理。
throw 关键字,表示在程序中抛出一个自定义或者已存在的异常对象。
finally 关键字,在进行异常捕获时,建议加上,因为从实际开发的情况来看,有可能出现捕获不了的异常或错误。
异常处理标准模型,也即 try、catch、finally、throw、throws 关键字一起使用:
assert 是 jdk1.4 引入的关键字,表示断言。断言指的是程序执行到某行代码处时一定是预期的结果。默认情况下,解释程序时,不影响程序运行。启用断言使用-ea 参数,如:java -ea 类名称。但是启用断言后,不正确的判断抛出错误 java.lang.AssertionError。
代码示例如下:
评论