您的位置:首页 > 编程语言 > Java开发

Java易错知识点笔记

2016-06-13 12:27 519 查看
目录

组合与继承

值类型和引用类型的存储位置

数值类型的符号

默认值

方法签名

变量

static

数据类型大小

this

垃圾回收器

finalize

初始化

惰性初始化

初始化顺序

非静态实例初始化

可变参数列表

枚举类型 enum

类的访问权限

main方法与单元测试

继承中属性的访问和方法的调用

初始化基类构建过程中对基类构造器的调用

在构造器中调用方法

代理

tryfinally和主动清理

对toString方法的自动调用

名称屏蔽 覆写

选择组合还是继承

final

方法调用绑定

多态 私有方法 静态方法 构造器

协变返回类型

接口和抽象类FROMhttpblogcsdnnetfenglibingarticledetails2745123

使用接口的核心原因

接口中的方法类型和基本数据类型

多继承和向上转型

嵌套接口

private接口

内部类

this 与 new

匿名内部类

嵌套类

接口中的嵌套类

继承内部类

持有对象 容器

异常类

throw 与 throws

捕获异常与重新抛出

栈轨迹

异常链

字符串

格式化输出

组合与继承

建立新类时应该首先考虑使用组合,而不是继承,因为组合更加简单灵活。

值类型和引用类型的存储位置

值类型数据存储在栈(stack)中,使用
new
关键字创建的对象存储在堆(heap)中。

数值类型的符号

java中所有数值类型都有正负号,不存在无符号的数值类型。

默认值

当变量作为类的成员使用时java才会为其设置默认值,java**不会**为局部变量设置默认值。

若局部变量没有初始化编译器会报错。

如果一个域是静态的基本类型域,而且没有对它进行初始化,那么它就会获得基本类型的标准初值。

对象引用会被初始化为
null


方法签名

方法名和参数列表合起来称为方法签名。

方法签名唯一标识出某个方法。

变量

局部变量:方法中的变量和域(即{})中的变量是局部变量。

成员变量:类中的变量。

static

static
关键字不能应用于局部变量,因此它只能作用于域。

static
字段和方法必须与某个对象关联,然后通过对象访问。

static
字段和方法不必与某个对象相关联,可以通过对象访问,也可以在没有创建对象的情况下直接通过类名访问。

不能在
static
域中访问非
static
域的方法。

某类中含有
static
字段 i,那么该类的不同对象中的字段 i 都指向同一个存储空间,在一个对象对 i 进行操作都会影响其他对象中的 i 。一个
static
字段对每个类来说都只有一个存储空间,而非
static
字段则是对每个对象都有一个存储空间。

static
方法可以创建或使用与其类型相同的被命名对象。

构造器虽然没有显式地使用static关键字,但也是静态方法。

静态初始化动作只执行一次,静态代码块也只执行一次。

数据类型大小

java中没有sizeof()方法,因为在java中所有的基本数据类型在所有的机器中所占的存储空间的大小都是相同的。

this

this
关键字只能在方法内部使用,表示对调用方法的那个对象的引用

如果在方法内部调用同一个类的另一个方法,不必使用
this
关键字,可以直接调用。

垃圾回收器

垃圾回收期只知道释放由
new
分配的内存。

垃圾回收只与内存有关。

finalize()

该函数不等同于析构函数!

如果定义了该函数,那么一旦垃圾回收器准备好释放对象占用的内存空间,将首先调用其
finalize()
方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

初始化

需要注意:虽然编译器强制在构造器起始处就初始化基类,但是并不强制初始化成员对象。

惰性初始化

在正要使用对象之前才初始化对象,例如使用
if
判断对象是否为
null
,如果为
null
则初始化。

在不是每次都必要生成对象的情况下,惰性初始化可以减少额外的负担。

初始化顺序

在类的内部,变量定义的顺序决定了初始化的顺序。

即使变量定义(对象声明)散布与方法定义之间,它们仍会在任何方法(包括构造器)被调用之前得到初始化。

先初始化静态对象,然后初始化非静态对象。

非静态实例初始化

在对象声明语句之后(有 ; 分隔),在一对花括号中写入对象初始化的语句。

对象初始化的语句会在调用构造器之前执行。

这种语法对于支持匿名内部类的初始化来说是必须的。

可变参数列表

<函数名>(<类/类型名>… <形参名>);

使用可变参数列表不依赖自动包装机制,实际上使用的是基本类型。

在函数重载中使用可变参数列表时,当调用无参的函数会导致编译器无法判断调用哪个函数。

如果在函数重载时为可变参数列表添加非可变参数,那么应该为该函数的每个重载版本都添加非可变参数。

枚举类型 enum

按照命名惯例,枚举中的具名值全部大写,多个单词之间用下划线间隔。

枚举可以用在
switch
中。

类的访问权限

对于类(内部类除外)的访问权限,只能是包访问权限或 public 。

将类的构造器设为
private
可以组织其他人创建该类的对象,也会阻碍给类被继承。

如果具有包访问权限的类中含有
public
类型的
static
成员,那么在包外可以调用该
static
成员。

main()方法与单元测试

为方便进行单元测试,可以在每个类中添加一个静态的main()方法。

单元测试之后,无需删除main()方法,可以下次测试时使用。

类中含有静态的main()方法,即使该类不是
public
类型也可以调用该类的main()方法。

继承中属性的访问和方法的调用

子类会继承基类的
private
属性,但是无法直接访问。

在子类中可以通过基类的 get/set 方法访问基类的
private
属性。

基类引用指向子类对象后,使用基类引用调用子类中的新增方法时,需要显式向下转型。

初始化基类:构建过程中对基类构造器的调用

构建过程是从基类向外扩散的,基类在子类构造器可以访问它之前就完成了初始化。

即使不为基类创建构造器,编译器也会自动合成默认构造器,并在该构造器中调用基类构造器。

使用
super
调用基类方法的语句要写在子类方法的第一句。

在构造器中调用方法

如果在构造器中调用动态绑定的方法,可能在调用时该方法所操纵的成员还未进行初始化,这会导致错误。

构造器中唯一能安全调用的方法是基类中的
final
方法(也适用于
private
方法)。

代理

在组合和继承之外,还可以为其他对象提供一个代理以控制对该对象的访问。

通过代理,能有效控制对实际委托累对象的直接访问,也可以很好的隐藏和保护实际对象,实施不同的控制策略。

try{}finally{}和主动清理

无论
try
中的子句如何退出,
finally
中的子句一定会执行(没有
catch
)。

可以在
finally
中定义一些清理方法,不要使用
finalize()
方法。

对toString()方法的自动调用

当编译器期望得到
String
类型的数据但是却得到了其他类型的数据时,若得到的数据类型中含有
toString()
方法,那么编译器会自动调用
toString()
方法。

名称屏蔽 覆写

如果基类中的某个方法已经被重载,那么在子类中重新定义同名方法并不会屏蔽该方法在基类中的任何版本。

当需要覆写已经在基类中被重载了的方法时,需要使用
@Override
注解。

选择组合还是继承

组合通常用于想在新类中使用现有类的功能但要使用新的接口形式这种情况。

使用继承通常意味着正在使用一个通用类,并且为了某种需求而将其特殊化。

通过继承来表达is-a(是一个)关系,通过组合来表达has-a(有一个)关系。

如果必须涉及向上转型,那么继承时必要的。

final

java中
final
常量只能是基本数据类型,并且在定义时即赋值(或定义空白
final
然后在构造器中赋值)。

一个即使
static
又是
final
的域只能占据一段不能改变的存储空间。

对于
final
引用,
final
只是使引用恒定不变,即不能再使引用指向别的对象,而被引用的对象自身是可以修改的 。

final
参数:参数在该方法中只读,方法无法更改参数引用所指向的对象,通常用于向匿名内部类传递数据。

只有在想要明确禁止覆盖时才使用
final
方法,不要使用
final
来提升方法效率。

方法调用绑定

绑定是指把对方法的调用与方法的主体关联起来。

前期绑定指在程序执行前进行绑定。

面向过程的语言默认使用前期绑定。

后期绑定指在运行时根据对象的类型进行绑定。

后期绑定又称为动态绑定或运行时绑定。

Java中除了
static
方法和
final
方法(
private
属于
final
)外,都使用后期绑定。

多态 私有方法 静态方法 构造器

只有非
private
方法才可以被覆盖。

静态方法时与类,而非单个对象相关联的,故静态方法不具有多态性。

构造器属于静态方法。

协变返回类型

在Java SE5中添加了协变返回类型。

协变返回类型指在子类中的被覆盖方法可以返回在基类中的该方法的返回类型的子类类型。

接口和抽象类(FROM:http:###blog.csdn.net/fenglibing/article/details/2745123)

接口是对动作的抽象,抽象类是对根源的抽象。

接口表示这个对象能做什么,抽象类表示这个对象是什么。

接口中所有方法都是抽象的,抽象类可以实现部分方法。

当关注一个事物的本质时使用抽象类,当关注一个事物的操作时使用接口。

含有抽象方法的类必须声明为抽象类。

基类中的抽象方法一定要在子类中覆写,除非子类也是抽象类。

接口可以继承(
extends
)接口,但不能实现(
implements
)接口,不能继承类。

子接口中不用重新声明父接口中的方法,但实现子接口的类中要实现子接口和父接口中的所有方法。

使用接口的核心原因

为了能够向上转型为多个基类类型。

防止创建该类的对象,并确保这仅仅是建立一个接口。

如果某事物应该成为一个基类,那么优先考虑使它成为一个接口。

接口中的方法类型和基本数据类型

接口中所有的方法都被默认(隐式)定义为
public
类型。

接口中的基本数据类型都被隐式地声明为
public static final
类型。

在Java SE5之前没有枚举类型,可以通过接口的该特性实现枚举的效果。

多继承和向上转型

只可以继承一个类但可以实现多个接口。

implements 关键字要放在 extends 关键字后面,多个接口之间用”逗号”隔开。

实现多个接口的子类可以向上转型为每个接口类型。

接口可以继承(extends)多个接口,每个接口间使用逗号”隔开”。

实现多个接口时应尽量避免接口中含有同名方法。

嵌套接口

可以在类中或接口种嵌套接口。

不可以在接口中嵌套
private
接口。

可以在类中嵌套
private
接口,但是该接口只能在该类中实现。

实现某个接口并不要求实现嵌套在其内部的任何接口。

private接口

private
接口强制该接口中的方法定义不可添加任何类型信息(不允许向上转型)。

只有有权使用
private
接口的对象才能使用对该
private
接口的引用。

内部类

内部类拥有对其外部类的所有元素的访问权,包括
private
元素。

除嵌套类外,必须使用外部类对象才能创建内部类对象。

方法中的内部类在方法外不可见。

.this 与 .new

.this
用于生成对该内部类的外部类的对象的引用。

.new
用于生成对该外部类的内部类的对象的引用。

匿名内部类

匿名类不可能有命名构造器(因为没有名字);

若在匿名内部类中使用在其外部定义的对象,则要求该对象的参数引用时
final
类型的。

嵌套类

static
类型的内部类称为嵌套类

创建嵌套类对象并不需要其外部类的对象。

不能从嵌套类的对象中访问非静态的外部类对象。

普通内部类的字段与方法只能放在类的外部层次上,所以普通内部类不能含有
static
数据和字段。

接口中的嵌套类

嵌套类可以作为接口的一部分,并且可以实现其外围接口。

接口内部的嵌套类可以用来差创建一些公共代码,以被接口的多有不同实现公用。

继承内部类

继承内部类时需要借助外部类对象。

需要将构造器参数设为外部类对象,在构造器中调用
<外部类对象>.super()


持有对象 容器

数组将数字与对象联系起来。

List也建立数字索引与对象的关联,List能自动扩容。

Collection保存单一的元素,Map保存相关联的键值对。

Map是一种将对象(而非数字)与对象关联的设计。

HashMap设计用来快速访问。

Set不接受重复元素。

如果要进行大量的随即访问则使用ArrayList;如果要经常从表中间插入或删除元素则使用LinkedList。

各种Queue以及栈的行为,由LinkedList提供支持。

新程序中不应该使用过时的Vector、Hashtable和Stack。

异常类

Throwable类是所有异常类型的根类。

Exception是与编程有关的所有异常类的基类,是Throwable的子类。

所有标准异常类都有两个构造器:一个是默认构造器;另一个是接受一个字符串参数的构造器。

throw 与 throws

throw
用于在方法中抛出一个异常对象。

throws
用于方法声明,多个异常用逗号隔开,表示该方法执行时可能发生这些异常。

如果方法中使用
throw
抛出异常,那么必须对方法进行异常声明。

当方法使用
throws
进行异常声明后,调用方法时必须对其进行异常捕获。

当覆盖方法时,只能抛出在基类方法的异常说明里列出的那些异常。

异常限制对构造器不起作用,子类构造器可以抛出任何异常,但是子类构造器的异常说明中必须包含基类构造器的异常说明。

子类方法可以不抛出任何异常,即使是基类所定义的异常。

若接口中方法含有异常声明,实现类中的方法可以不含有异常声明;但如果接口中方法没有异常声明,实现类中方法不能有异常声明。

捕获异常与重新抛出

当有多个
catch
时,只要其中一个捕获到异常,就会终止方法,接下来的
catch
不会继续执行。

抛出异常的时候,异常处理系统会按照代码的书写顺序匹配最近的处理程序。

子类对象可以匹配其基类的处理程序。

无论异常是否发生,
finally
块总会执行,即使是涉及到
break
continue
return
时也会执行。

catch
中将当前异常对象重新抛出时,
printStackTrace()
方法显示的是原来的异常抛出点的调用栈信息,而非重新抛出点的信息。

想要更新这个信息,可调用
fillInStackTrace()
方法,这将返回一个Throwable对象,它把当前调用栈信息填入原来的异常对象。

栈轨迹

printStackTrace()
方法打印从方法调用处直到异常抛出处的方法调用序列。

printStackTrace()
方法所提供的信息可以通过
getStackTrace()
方法来直接访问。

getStackTrace()
方法返回一个由栈轨迹中的元素构成的数组,其中每一个元素都表示栈中的一帧。

元素 0 是栈顶元素,并且是调用序列中的最后一个方法(Throwable对象被创建和抛出之处)。

数组中最后一个元素和栈底是调用序列中的第一个方法调用。

异常链

在捕获一个异常后抛出另一个异常,并把原始异常信息保存下来,这被称为异常链。

在 JDK 1.4 以后,Error、Exception和RuntimeException中提供了接受一个cause对象参数的构造器,这个cause用于表示原始异常。

如果要将其他类型的异常链接起来,应该使用
initCause()
方法而不是构造器。

字符串

String对象是不可改变的,String类中每个会修改String值的方法,都会创建一个新的String对象,以包含修改后的字符串内容。

String对象作为方法参数时,传递的是引用的一个拷贝,方法不会对原来的String对象产生影响。

StringBuffer与StringBuilder是可变的有序字符串序列,StringBuffer是线程安全的,StringBuilder不是线程安全的。

在字符串不经常变化的场景使用String。

在频繁进行字符串运算的多线程环境中使用StringBuffer。

在频繁进行字符串运算的单线程环境中使用StringBuilder。

格式化输出

在Java SE5中推出了c语言中
printf()
风格的格式化输出功能。

System.out.format()
System.out.printf()
是等价的,它们的参数语法兼容与c语言语法。

Formatter.format()
接受与
printf()
相同的参数并将信息输出到System.out。

String.format()是一个
static
方法,该方法接受与
printf()
相同的参数但返回一个String对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息