写点什么

java 之扩展概念

作者:andy
  • 2022-10-28
    北京
  • 本文字数:3987 字

    阅读完需:约 13 分钟

扩展概念是对面向对象思想中的封装性、继承性以及多态性在 Java 中的应用的进一步阐述。


一、Object 类


Java 中引用数据类型包括类、接口、数组,如何进行统一管理呢?

Object 类是所有引用数据类型的父类,通过对象的多态性,实现各种类型的管理。对于接口,比较特殊。

为什么 Object 类中有一个无参构造方法?

Object 源码中没有显式展示无参构造,但是系统编译时会自动生成。对于 Object 类的无参构造,主要是在子类进行实例化时,默认首先执行 Object 父类的无参构造,满足继承性特点。

对于 Object 类,需要注意以下方法,这些方法是在 Java 类开发中经常覆写的方法。


// 显示类中的属性信息public String toString() {    return getClass().getName() + "@" + Integer.toHexString(hashCode());}
// 对象比较public boolean equals(Object obj) { return (this == obj);}// hashcode方法,用于对象比较和存储对象地址定位,在集合中起到非常重要的作用public native int hashCode();
// 反射public final native Class<?> getClass();
// 克隆(使用该方法,需要强制子类实现cloneable接口)protected native Object clone() throws CloneNotSupportedException;
// 通知public final native void notify();
// 通知所有阻塞线程public final native void notifyAll();
// 等待public final native void wait(long timeout) throws InterruptedException;
//垃圾处理protected void finalize() throws Throwable {}
复制代码


注意:

1、开发的代码不重要,主要是怎么分析,怎么解构问题,即解决问题的能力;

2、对于对象比较,如果是集合结构中进行查找和删除指定内容,建议覆写 Object 类的 hashCode()和 equals()方法来实现,如果是进行集合排序,则可以实现 Comparable 接口,通过 compareTo()方法实现。当然,查找和删除指定内容也可以通过 Comparable 接口实现,但是因为所有类都是 Object 的子类,这样更加方便一些。

3、对于覆写垃圾回收处理的 finalize()方法,需要注意引用强弱的问题,尤其强引用和软引用。


二、匿名内部类


为了能够临时使用接口和抽象类,又不用定义子类为长期使用,可以使用匿名内部类解决。

匿名内部类是基于接口或者抽象类而应用的。通常而言,一个 Java 文件,只是适合编写一个类,那么,对于接口和抽象类而言,其子类就建议不要写在该文件中,或者,直接使用匿名内部类的方式使用接口或者抽象类,这样可以方便快速开发。

匿名内部类可以帮助用户减少类的开发。

也可以理解匿名内部类为匿名对象。


代码示例如下:


package org.fuys.ownutil.inheritance;abstract class Room {public abstract void live();}interface Key {	public void open();	public void lock();}public class AnonymityInstance {	public static void main(String[] args) {		Key key = new Key() {			@Override			public void open() {				System.out.println("open the door");			}			@Override			public void lock() {				System.out.println("lock the door");			}		};		key.open();		new Room() {			@Override			public void live() {				System.out.println("live");			}		}.live();		key.lock();	}}
复制代码


三、包装类


在 Java 面向对象思想中,一切皆对象。但是,因为基本数据类型并非对象,因此,为了满足面向对象思想,故设计出了包装类。

包装类的设计思想便是设计的类中拥有对应基本数据类型的属性,用于存储基本数据类型数据

包装类分为以下两种:

对象型包装类(Object 直接子类):Character、Boolean

数值型包装类(Number 直接子类):Byte、Short、Integer、Long、Float、Double

Java1.5 之前包装类包含以下操作,即装箱和拆箱。但是在 jdk1.5 新特性之后,Java 提供自动装箱和自动拆箱,并能够利用包装类的对象进行数学计算。这样的方式,大大提高了数据类型的选择,基本数据类型也能够像引用数据类型进行操作,方便了开发。

增加了自动装箱和自动拆箱,但是对于数据类型的存储方式,并没有改变,基本数据类型存储在栈空间。


代码:


Integer a = 10;		Integer b = 10;		Integer c = new Integer(10);		System.out.println(a==b);		// true		System.out.println(a==c);		// false		System.out.println(b==c);		// false		System.out.println(b.equals(c));// true
复制代码


注意:包装类一般不使用构造方法装箱,对象值比较实用 equals。标红地方会有结果不同,类似于字符串直接赋值和构造方法赋值的原理

代码:


Object obj = 10;		int num = (int) obj;		System.out.println(num * 2);
复制代码


注意:对于 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 关键字一起使用:


package org.fuys.ownutil.instance;class MyException {	public static int div(int x, int y) throws Exception {		int result = 0;		System.out.println("1,begin to div");		try {			result = x / y;		} catch (Exception e) {			throw e;		}finally {			System.out.println("2,end to div");		}		return result;	}}public class ExceptionInstance {	public static void main(String[] args) {		try {			MyException.div(10, 0);		} catch (Exception e) {			e.printStackTrace();		}	}}
复制代码


assert 是 jdk1.4 引入的关键字,表示断言。断言指的是程序执行到某行代码处时一定是预期的结果。默认情况下,解释程序时,不影响程序运行。启用断言使用-ea 参数,如:java -ea 类名称。但是启用断言后,不正确的判断抛出错误 java.lang.AssertionError。


代码示例如下:


int result = 0;		try {			result = Math.div(10, 0);		} catch (Exception e) {			e.printStackTrace();		}finally{			try {				assert result == 10:"Result is not 10";			} catch (Throwable e2) {				e2.printStackTrace();			}		}
复制代码


用户头像

andy

关注

还未添加个人签名 2019-11-21 加入

还未添加个人简介

评论

发布
暂无评论
java之扩展概念_andy_InfoQ写作社区