Java中修饰变量和方法的关键字总结分析

Java关键字我们接触的也都不少了,就以这篇文章收录下一些特殊使用的关键字,作为深入学习的记录。

一、修饰变量的关键字

1.transient
  将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。
https://baijiahao.baidu.com/s?id=1636557218432721275&wfr=spider&for=pc

2.volatile
当一个变量定义为 volatile 之后,将具备两种特性:
  (1)保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存(详见:Java内存模型)来完成。
  (2)禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。
  
https://www.cnblogs.com/dolphin0520/p/3920373.html
https://www.cnblogs.com/zhengbin/p/5654805.html

二、修饰方法的关键字

1.synchronized
(1)修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

public void method()
{
   synchronized(this) {
      // todo
   }
}

(2)修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

public synchronized void method()
{
   // todo
}

(3)修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

public synchronized static void method() {
   // todo
}

(4)修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。

class ClassName {
   public void method() {
      synchronized(ClassName.class) {
         // todo
      }
   }
}

注意:
上面说到的“这个类的所有对象”其实指的就是当前类的Class实例,Class数据存在永久代中,是该类的一个全局锁。

总结:
(1)无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
(2)每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
(3)实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

2.native
  native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。
  一个native方法就是一个Java调用非Java代码的接口。在定义一个native方法时,并不提供实现体(比较像定义一个Java Interface),因为其实现体是由非Java语言在外面实现的。

Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI(Java Native Interface)接口调用其他语言来实现对底层的访问。
在这里插入图片描述
JNI 调用C流程图:
在这里插入图片描述

3.strictfp
  Java2新增的关键字。strictfp的意思是FP-strict,strict float point (精确浮点),也就是说精确浮点的意思。
  strictfp 关键字可应用于类、接口或方法;但是不允许对接口中的方法以及构造函数声明strictfp关键字。
  在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时,Java的编译器以及运行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。而一旦使用了strictfp来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。

public strictfp class MyClass{}
public strictfp double add(float a, double b){}

4.abstract
可用于修饰类或方法,表示抽象类和抽象方法。
(1)抽象方法
1)抽象方法跟普通方法是有区别的,它没有自己的主体(没有{}包起来的
业务逻辑),跟接口中的方法有点类似。所以我们没法直接调用抽象方法。
2)抽象方法不能用private修饰,因为抽象方法必须被子类实现(覆写),而private权限对于子类来说是不能访问的,所以就会产生矛盾。
3)抽象方法也不能用static修饰,试想一下,如果用static修饰了,那么我们可以直接通过类名调用,而抽象方法压根就没有主体,没有任何业务逻辑,这样就毫无意义了。

(2)抽象类
1)用abstract关键字来表达的类,其表达形式为:(public)abstract class 类名{}
2)抽象类不能被实例化,也就是说我们没法直接new 一个抽象类。抽象类本身就代表了一个类型,无法确定为一个具体的对象,所以不能实例化就合乎情理了,只能有它的继承类实例化。
3)抽象类虽然不能被实例化,但有自己的构造方法(这个后面再讨论)
4)抽象类与接口(interface)有很大的不同之处,接口中不能有实例方法去实现业务逻辑,而抽象类中可以有实例方法,并实现业务逻辑,比如我们可以在抽象类中创建和销毁一个线程池。
5)抽象类不能使用final关键字修饰,因为final修饰的类是无法被继承,而对于抽象类来说就是需要通过继承去实现抽象方法,这又会产生矛盾。

(3)抽象类与抽象方法的关联
1)如果一个类中至少有一个抽象方法,那么这个类一定是抽象类,但反之则不然。也就是说一个抽象类中可以没有抽象方法。这样做的目的是为了此类不能被实例化。
2)如果一个类继承了一个抽象类,那么它必须全部覆写抽象类中的抽象方法,当然也可以不全部覆写,如果不覆写全部抽象方法则这个子类也必须是抽象类(这样做就无意义了)

疑问1:为什么抽象方法不能实例化却有构造器呢?
  我们知道调用子类对象的时候,会优先调用父类的构造方法初始化,因为抽象类在有抽象方法的时候,抽象方法的实现是由子类继承并重写来实现的,若抽象类没有构造器,那就也就没有继承实现这一说了。
疑问2:抽象类中的非静态和非抽象方法中的this关键字指的是什么?
  指的是派生类,而并非抽象类本身,因为抽象类本身不能实例化。如果有多个继承类,谁调用this就代表谁。

三、公共的(即能修饰变量,也能修饰方法)

1.public
  对任何人都是可用的。

2.private
  除类型创建者和类型的内部方法之外的任何人都不能访问的元素。

3.protected
  继承的类可以访问以及和private一样的权限。

4.static
  static表示“全局”或者“静态”的意思,用来修饰成员变量成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
  被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内一定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象
  用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,而是
类的所有实例共享同一个static变量
。 static变量前可以有private修饰,private是访问权限限定,表示这个变量可以在这个唯一类的静态代码块中,或者这个唯一类的其他静态成员方法中使用,但是不能在其他类中通过类名来直接引用。static表示不要实例化就可以使用。

5.final
final关键字可以用来修饰引用、方法和类。
(1)用来修饰一个引用
  1) 如果引用为基本数据类型,则该引用为常量,该值无法修改;
  2)如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
  3)如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
(2)用来修饰一个方法
  当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
(3)用来修饰类
  当用final修改类时,该类成为最终类,无法被继承。简称为“断子绝孙类”。

6.synthetic
  编译器通过生成一些在源代码中不存在的synthetic方法和类的方式,实现了对private级别的字段和类的访问,从而绕开了语言限制,这可以算是一种trick。
  在实际生产和应用中,基本不存在程序员需要考虑synthetic的地方。
在此提一个的常见的存在synthetic的案例:
  如果同时用到了Enum和switch,如先定义一个enum枚举,然后用switch遍历这个枚举,java编译器会偷偷生成一个synthetic的数组,数组内容是enum的实例。

java修饰关键字包括public、protected、private、default等,用于控制类、方法变量的访问权限。public表示公开的,可以在任何地方访问;protected表示受保护的,可以被同一个包的类访问,也可以被不同包的子类访问;private表示私有的,只能在同一个类的内部访问;default表示默认的,即没有修饰符,默认在同一个包可见。 Java的返回值类型指的是方法返回的数据类型。在Java,每个方法都有一个返回值类型,用于指示方法返回的数据类型。返回值类型可以使基本数据类型(如int、float等)或引用数据类型(如String、Array等)。在方法声明时,使用关键字void表示该方法没有返回值,如果有返回值,则在方法声明时指定返回值类型。 下载指的是从互联网或其他存储介质上将文件复制到本地计算机上。在Java,可以使用输入流和输出流来实现文件的下载。通过输入流将文件从远程服务器或网络上读取到内存,然后通过输出流将文件写入本地计算机的指定位置。使用修饰关键字可以控制下载方法的访问权限,返回值类型可以指定下载方法返回的数据类型。 综上所述,Java修饰关键字用于控制访问权限,返回值类型用于指定方法返回值的数据类型,下载指的是从互联网或其他存储介质上将文件复制到本地计算机上。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值