JAVA基础3——常见关键字解读(1)

时间:2022-03-28 11:17:12

常见的JAVA中的关键字

static

static静态变量

静态变量:使用static关键字定义的变量。static可以修饰变量和方法,也有static静态代码块。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。

static修饰的field字段,不管类初始化多少遍,此field对象只会初始化一次,且所有new出来的类对象中,对此static修饰的field字段进行操作,其余所有的类对象中的此field值都会被改变。

静态变量的优势:

A,静态对象的数据在全局是唯一的,一改都改。如果你想要处理的东西是整个程序中唯一的,弄成静态是个好方法。 非静态的东西你修改以后只是修改了他自己的数据,但是不会影响其他同类对象的数据。

B,引用方便。直接用 类名.静态方法名 或者 类名.静态变量名就可引用并且直接可以修改其属性值,不用get和set方法。

C,保持数据的唯一性。此数据全局都是唯一的,修改他的任何一处地方,在程序所有使用到的地方都将会体现到这些数据的修改。有效减少多余的浪费。

注意:static静态变量是线程非安全的,静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。

static静态方法

使用约束点:

  1. static方法中无法访问非static全局变量;
  2. static方法中无法访问非static方法;
  3. static方法中无法使用this和super关键字(因为this关键字指向该方法所属的对象,而静态方法是属于类级的,不存在对象一说;至于super关键字,只要不是用在构造方法里,那么它就是指向父类对象的,而静态方法是不能引用实例对象的,因此也不能使用super关键字)。

静态方法的多线程问题分析:

  1. 如果静态方法中没有使用全局变量,则肯定是线程安全的;
  2. 如果访问且修改了全局静态变量,可能会出现数据不一致问题,线程非安全。
  3. 是否会出现线程等待卡死?(待确认)

final

一言概之,final即为“最终的、最后的”的意思,使用final类似于一种显式的声明,强调这个final所修饰的内容是不可变更的。

  1. final修饰的变量:此变量的值不能被修改、不能被重复赋值(声明的时候、代码块、构造函数三者任选一个地方初始化,有且只能有一个地方初始化值,其余地方不能修改其值);
  2. final修饰的类:此类不能被继承;
  3. final修饰的方法:此方法不可被子类重写,用于父类中为了防止子类覆写某些特殊的方法(在早期的JAVA版本中,对于final方法,编译的时候会转换位内嵌调用提升性能,但是近期的JAVA版本中已经不再需要final进行方法优化了,所以不再考虑此情况了)。

对final修饰变量的情况具体说明如下:

final修饰变量为基本类型时

final修饰基本类型的变量的时候,此变量值不可变更,不可修改,不可重新赋值。

final修饰变量为基本类型时

final修饰引用类型的变量的时候,此变量不可被重新赋值,但是此变量的对象内容可以被修改。可以理解为final固定了此变量指向的对象地址,但是对于此对象中的内容属性,是可以修改的。

final的其它冷知识

  1. 类的private方法,会被隐式的指定为final类型的。
  2. 当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。看下面这个例子:
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println((a == c));
System.out.println((a == e));
}
} 输出:
true
false
因为b已经声明为final且值固定,编译期的时候就已经将c编译为hello2,与a相同,所以第一个是true。

更详细的解释,可以参考下http://www.cnblogs.com/dolphin0520/p/3736238.html,解释的很到位,举的例子也很好。

final 与 finalize() 区别####

final关键字是用于标示不可修改、不可变更相关的含义,具体上面已经说明了。

finalize()是个方法名,Object对象默认提供一个protected类型的此方法。此方法尽量不要在代码中主动去调用。

finalize()的功能 : 一旦垃圾回收器准备释放对象所占的内存空间, 如果对象覆盖了finalize()并且函数体内不能是空的, 就会首先调用对象的finalize(), 然后在下一次垃圾回收动作发生的时候真正收回对象所占的空间.finalize()有一个特点就是: JVM始终只调用一次. 无论这个对象被垃圾回收器标记为什么状态, finalize()始终只调用一次. 但是程序员在代码中主动调用的不记录在这之内.

尽量避免使用finalize():

  1. finalize()不一定会被调用, 因为java的垃圾回收器的特性就决定了它不一定会被调用
  2. 就算finalize()函数被调用, 它被调用的时间充满了不确定性, 因为程序中其他线程的优先级远远高于执行finalize()函数线程的优先级。也许等到finalize()被调用, 数据库的连接池或者文件句柄早就耗尽了.
  3. 如果一种未被捕获的异常在使用finalize方法时被抛出,这个异常不会被捕获,finalize方法的终结过程也会终止,造成对象出于破坏的状态。被破坏的对象又很可能导致部分资源无法被回收, 造成浪费.
  4. finalize()和垃圾回收器的运行本身就要耗费资源, 也许会导致程序的暂时停止.

finally

常常与try...catch语句一起出现,用于保证try语句执行完成之后总会执行finally语句,在finally中常常进行一些资源释放等操作。

即使在try语句中有return操作、或者出现某些没有catch住的运行时异常需要提前退出的时候,也会执行finally语句。

看下下面这个代码片段:

private static int test()
{
int i = 1;
try
{
return i;
}
finally
{
i = 2;
}
}
执行结果:
1

test()方法执行的返回值是1,即虽然在return之前会执行一下finally中的方法,但是在finally中对返回对象进行重新赋值操作是不会改变原有待返回的值的。

通常情况下,尽量避免在finally分支中进行赋值操作,因为也不会生效,主要是用于一些资源的释放操作。

throw & throws

throw 是具体的语句抛出异常。

throws 是方法声明的时候声明可能抛出的异常时使用。

abstract

abstract 可以用于修饰类或者方法。

如果将一个类设置为abstract,则此类必须被继承使用。此类不可生成对象,必须被继承使用。 Abstract可以将子类的共性最大限度的抽取出来,放在父类中,以提高程序的简洁性。 Abstract虽然不能生成对象,但是可以声明,作为编译时类型,但不能作为运行时类型。 Final和abstract永远不会同时出现。

当abstract用于修饰方法时,此时该方法为抽象方法,此时方法不需要实现,实现留给子类覆盖,子类覆盖该方法之后方法才能够生效。 如果方法想要声明为abstract,则此方法所在的类必须也是abstract类型的。子类必须实现父类中的abstract方法, 否则编译会报错。