目录
一.前言
本文基于jdk11
这些基本知识非常有趣,对于Java初学者而言是很简单的,但是对于已经学习Java一段时间的人来说,可能记忆不是那么清晰,对一些基本概念认识的比较模糊,所以在这里详细地记录下来。
二.重点知识
1.类的静态变量、实例变量、局部变量、成员变量,静态方法、实例方法、成员方法的区别以及部分修饰符的使用
1)成员变量与成员方法
成员变量、成员方法查询资料有异议。我是这样理解的,类的直接成员组成分为两部分:变量和方法。方法我们叫成员方法,变量我们叫成员变量。因此成员变量应该是包含静态变量和实例变量的一个泛称,成员方法应该是包含静态方法和实例方法的一个泛称 。但是,由于静态变量、静态方法比较特殊,所以,成员变量一般语义下认为是实例变量,成员方法一般语义下认为是实例方法。具体要根据上下文判断。
随着学习的深入,我们会发现,一些教材或相关从业人员会把实例变量称为字段。这是因为数据库的表结构主要由字段构成,这些字段对应于PO(持久化对象)中的实例变量,所以,大家习惯性地称这些实例变量为字段。慢慢地,不仅仅是对应于PO中的实例变量被称为字段,POJO(普通Java对象)中的实例变量也被称为字段,还衍生出了静态变量被称为静态字段等。
名称 | 特定修饰符 | 定义位置 | 作用域 | 用法 | 描述 |
---|---|---|---|---|---|
静态变量 | static | 方法外 | 类内 | 类名.变量名 | 类的属性,又名类变量 |
实例变量 | - | 方法外 | 类内 | 由对象调用 | 对象的属性 |
局部变量 | - | 方法内 | 方法内 | - | - |
- | - | - | - | - | - |
静态方法 | static | 类内 | - | 类名.变量名 | 类的属性,又名类方法 |
实例方法 | - | 类内 | - | 由对象调用 | 对象的属性 |
注:
- 静态变量、静态方法也可以通过对象直接调用,但不推荐。
- Java中的全局变量一般指的是静态变量,也有指实例变量的说法,具体看语境。
- static方法中不能使用this或supper关键字。
2)修饰符(部分)
名称 | 访问修饰符 | 其他修饰符 | 其他 |
---|---|---|---|
类 | 默认、public | abstract、final | 内部类可以被static修饰 |
成员变量 | private、默认、protected、public | static、final | - |
成员方法 | private、默认、protected、public | static、abstract、final | - |
局部变量 | - | final | - |
- | - | - | - |
接口 | 默认、public | - | - |
成员变量 | private、public | static final | 默认修饰符是public static final,即是个公共常量 |
成员方法 | private、public | static、abstract、default | 默认修饰符是public abstract,即是个公共抽象方法 |
注:
- 被final修饰的类、方法不能被继承。编译器会优化final类。
- 被final修饰的实例变量可以只声明,但在构造函数中必须初始化且每个对象只能被赋值一次;
- 被final修饰的静态变量被称为常量,在声明时必须初始化且只能赋值一次;
- 被final修饰的局部变量可以只声明,但在使用时必须初始化且只能赋值一次,其值在变量存在期间不会改变。
- 接口中的成员变量一定是常量,可以显示声明为private。
- 接口中的成员方法可以显示声明为带有方法体的private方法、private/public static方法、default方法
- 默认是缺省的意思。
- abstract 与 static或final 不能同时使用。
1))为什么只有被final修饰的静态变量是常量?
final:表示最终的、不可改变的,只能被赋值一次。
首先被static修饰的静态变量依存于类;其次被final修饰的静态变量在声明时必须初始化。最后类是唯一的。所以是常量。
被final修饰的实例变量为什么不是常量呢?
首先没有被static修饰的实例变量依存于对象;其次被final修饰的实例变量可以只声明,在构造函数中初始化;最后一个类在实例化多个不同对象的时候初始化的值可能不同。所以被final修饰的实例变量在每个对象中可能是不同的,不能称为常量。
被final修饰的局部变量为什么不是常量呢?
首先被final修饰的局部变量可以只声明,在使用时初始化;其次方法可以传入参数初始化被final修饰的局部变量;最后不同的对象调用方法时可能传入不同的参数。所以被final修饰的局部变量在每个对象中可能是不同的,不能称为常量。 删除线部分是正确的,但不够完善。待完善
2.创建自定义异常时,继承RuntimeException与继承Exception的区别
RuntimeException是Exception的子类,表示运行时异常,是非编译异常。即:不抛出不捕获也可以通过编译器,编译器不会提示程序员是否有错。比如:1/0,只有在程序运行后才会抛出异常,并终止程序。
Exception除了RuntimeException一个子类外,还包括一些其他的子类,比如SQLException等,只是除了RuntimeException外,其他子类(包括自定义继承该类的类)都是非运行时异常,是编译异常。即:要么抛出要么捕获,否则无法通过编译器,在IDE环境下,编译器一般会将需要处理异常的代码标红,以提示程序员需要处理。比如:conn.prepareStatement(sql),操作数据库预处理语句不处理异常会标红报错。
所以,区别是:
继承RuntimeException可以不对异常主动处理,但发生异常时会导致程序终止。
继承Exception必须对异常主动处理,既然已经处理,发生异常时就不会导致程序终止了。
3.实例instance与对象object的区别
在面向对象程序设计中,“类”在实例化之后叫做一个“实例”。 “类”是静态的,不占进程内存,而“实例”拥有动态内存。实例被用来模拟现实世界中存在的、具体的或原型的东西。
我们说创建一个对象,其实就是实例化一个对象,这个创建的过程就叫实例化,创建的结果就是实例,此时也可称这个实例是一个对象。此时的对象与实例没有区别。
但是在Java中有些类是不能被实例化的,比如抽象类,只有它的非抽象子类能够被实例化。我们假设Animal是抽象类,Dog是子类,则:Animal a = new Dog();
。这个时候我们就说Animal引用了一个对象,而不是说Animal创建了一个对象,这个对象不能称为实例,只能称为对象。
可以看到对象的表示范围更大,因此,实例是对象的具体表示,对象是一个特定的实例。
三.常用方法
1.复制数组
数组的数据类型是引用数据类型。复制一个数组需要深拷贝。java本身提供了很多深拷贝数组的方法。这里记录部分方法。
1)System.arraycopy()
推荐,效率最高。
@param src the source array.
@param srcPos starting position in the source array.
@param dest the destination array.
@param destPos starting position in the destination data.
@param length the number of array elements to be copied.
public static native void arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
2)Arrays.copyOf()
效率次于1)System.arraycopy() 。
该方法重载了很多,这里拿出一个说明,其他重载方法类似。
@param <T> the class of the objects in the array
@param original the array to be copied
@param newLength the length of the copy to be returned
@return a copy of the original array, truncated or padded with nulls to obtain the specified length
public static <T> T[] copyOf(T[] original, int newLength){...}
3)Object.clone()
效率次于3)Object.clone() 。
@return a clone of this instance.
protected native Object clone() throws CloneNotSupportedException;
才疏学浅,如果差错,还请批评指正。
学而不思则罔,思而不学则殆。
作者:@nokbita