Java中易错知识点整理

1.static

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

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

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

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

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

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

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

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

2.throw 与 throws


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

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

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

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

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

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

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

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

3. .this 与 .new

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

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

4.穿透现象

1、switch的穿透性能解决的问题
存在多个case分支的功能代码是一样时,可以用穿透性把流程集中到同一处处理,这样可以简化代码

2、例如:



跳转控制语句
break:跳出并结束当前所在循环的执行
continue:跳出当前循环的当次执行,进入本循环的下一次循环

5.捕获异常与重新抛出


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

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

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

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

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

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

6.格式化输出

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

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

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

String.format()是一个 static 方法,该方法接受与printf()相同的参数但返回一个String对象

7.多继承和向上转型

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

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

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

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

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

8.final

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

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

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

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

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

9.try{}finally{}和主动清理

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

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

10.finalize()

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

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

11.为什么 typeof null === object

        原理是这样的,不同的对象在底层都表示为二进制,在JavaScript中二进制前三位都为0的话会被判断为 obiect 类型,null 的二进制表示是全0,自然前三位也是0,所以执行 typeof 时会返回”object”。

12.注解

Java 中有以下几个元注解
@Target:注解的作用目标
@Retention:注解的生命周期,与JVM有关
@Documented:注解是否应当被包含在 JavaDoc(API) 文档中
@Inherited:是否允许子类继承该注解
Java 3大内置注解
@Override,@Deprecated,@SuppressWarnings
Class类通过实现AnnotatedElement接口来反射注解:Java反射机制解析注解主要是通过java.lang.reflect包下的提供的AnnotatedElement接口,Class<T>实现了该接口定义的方法,返回本元素/所有的注解(Annotation接口)。
反射注解的工作原理
1)首先,我们通过键值对的形式可以为注解属性赋值,像这样:@Hello(value = "hello")
2)接着,你用注解修饰某个元素,编译器将在编译期扫描每个类或者方法上的注解,会做一个基本的检查,你的这个注解是否允许作用在当前位置,最后会将注解信息写入元素的属性表
3)然后,当你进行反射的时候,虚拟机将所有生命周期在 RUNTIME的注解取出来放到一个 map 中,并创建一个 AnnotationInvocationHandler 实例,把这个 map 传递给它。
4)最后,虚拟机将采用 JDK 动态代理机制生成一个目标注解的代理类,并初始化好处理器。
Java的Annotation注解,可参考十分钟深度学习Java注解
Note:RetentionPolicy.SOURCE注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
注解处理器(APT,javac自带的一个工具),可参考【Annotation】Processing-Tool详解
junit中常见注解(@Before即每个@Test测试方法都会运行一次),可参考JUnit详解

13.字符串

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

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

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

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

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

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

14.字符型常量和字符串常量的区别?


1.形式 : 字符常量是单引号引起的一个字符,字符串常量是双引号引起的 0 个或若干个字符。
2.含义 : 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)。
3.占内存大小 : 字符常量只占 2 个字节; 字符串常量占若干个字节。

15.标识符和关键字的区别是什么?

在我们编写程序的时候,需要大量地为程序、类、变量、方法等取名字,于是就有了 标识符 。简单来说, 标识符就是一个名字 。

16.Java 语言关键字有哪些?

Tips:所有的关键字都是小写的,在 IDE 中会以特殊颜色显示。

default 这个关键字很特殊,既属于程序控制,也属于类,方法和变量修饰符,还属于访问控制。

在程序控制中,当在 switch 中匹配不到任何情况时,可以使用 default 来编写默认匹配的情况。
在类,方法和变量修饰符中,从 JDK8 开始引入了默认方法,可以使用 default 关键字来定义一个方法的默认实现。
在访问控制中,如果一个方法前没有任何修饰符,则默认会有一个修饰符 default,但是这个修饰符加上了就会报错。

⚠️注意 :虽然 true, false, 和 null 看起来像关键字但实际上他们是字面值,同时你也不可以作为标识符来使用。

17.自增自减运算符

在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1,Java 提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)自减运算符(–)

++ 和 – 运算符可以放在变量之前,也可以放在变量之后,当运算符放在变量之前时(前缀),先自增/减,再赋值当运算符放在变量之后时(后缀),先赋值,再自增/减

     例如,当 b = ++a 时,先自增(自己增加 1),再赋值(赋值给 b);当 b = a++ 时,先赋值(赋值给 b),再自增(自己增加 1)。也就是,++a 输出的是 a+1 的值,a++输出的是 a 值。用一句口诀就是:“符号在前就先加/减,符号在后就后加/减”。

18. 静态方法为什么不能调用非静态成员?

这个需要结合 JVM 的相关知识,主要原因如下:

1.静态方法是属于的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问
2.在类的非静态成员不存在的时候静态成员就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。

19. 静态方法和实例方法有何不同?

1、调用方式

在外部调用静态方法时,可以使用 类名.方法名 的方式,也可以使用 对象.方法名 的方式,而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象 。

不过,需要注意的是一般不建议使用 对象.方法名 的方式来调用静态方法。这种方式非常容易造成混淆,静态方法不属于类的某个对象而是属于这个类。

因此,一般建议使用 类名.方法名 的方式来调用静态方法。

 2、访问类成员是否存在限制

静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。

20.public,protected,private,default

 public: Java语言中访问限制最宽的修饰符,一般称之为“公共的”。被其修饰的类、属性以及方法不
     仅可以跨类访问,而且允许跨包(package)访问。
private: Java语言中对访问权限限制的最窄的修饰符,一般称之为“私有的”。被其修饰的类、属性以
     及方法只能被该类的对象访问,其子类不能访问,更不能允许跨包访问。
protect: 介于public 和 private 之间的一种访问修饰符,一般称之为“保护形”。被其修饰的类、
     属性以及方法只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问。
default:即不加任何访问修饰符,通常称为“默认访问模式“。该模式下,只允许在同一个包中进行访问

区别
1. public:可以被所有其他类所访问。
2. private:只能被自己访问和修改。
3. protected:自身,子类及同一个包中类可以访问。
4. default(默认):同一包中的类可以访问,声明时没有加修饰符,认为是friendly。

注意
继承的时候,他们的区别:
public 声明的在子类变为public
protected 声明的子类变为private
private 声明的在子类中不可用

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值