java关键字总结?

用法:类修饰符的一种,可以用来修饰类,方法,被修饰的类不能够实例化(即不能用new关键字得到对象),被修饰的方法不能够实现。一个抽象类中不一定要有抽象方法,但是一个类里面有抽象方法就一定是抽象类。如果由类要继承抽象类的话,必须要实现里面的抽象方法。构造方法和静态方法不可以修饰为抽象。

abstract关键字可以修改类或方法。

abstract类可以扩展(增加子类),但不能直接实例化。

abstract方法不在声明它的类中实现,但必须在某个子类中重写

采用abstract方法的类本来就是抽象类,并且必须声明为abstract。abstract类不能实例化。

仅当abstract类的子类实现其超类的所有abstract方法时,才能实例化abstract类的子类。这种类称为具体类,以区别于abstract类 。

abstract抽象用在类的声明中来指明一个类是不能被实例化的,但是可以被其他类继承。一个抽象类可以使用抽象方法,抽象方法不需要实现,但是需要在子类中被实现。它的用途是向子类提供通用的信息。抽象类可以包含正常的类包含的任何东西,也就是说,类和实例变量,以及带有任何修饰词的方法。只有抽象类可能有抽象方法。如果一个不是抽象的类包含一个抽象方法,那么将会出现编译错误。 
例子:如果下列的一个成立,那么一个有抽象方法:

 b.它从它的直接父类继承了一个抽象方法。 
c.一个直接的类的父借口声明或继承了它的一个方法(这因此必须是abstract) 

static方法总是可用的,因此必须有一个实现;static abstract将永远没有实现。

用法:一个类继承另一个类的关键字,当出现了这个关键字,两个类就有了继承关系,extends前面的类,我们称之为父类。

extends后面的类,我们称之为子类。有了继承关系之后,我们就说子类拥有父类继承下来的所有非私有的成员(包括了属性,方法),但是不包括构造方法 。

解释:最终的,决定性的 
用法:修饰符的一种,它可以用来修饰类,方法,属性。当一个属性被修饰成final的之后,这个属性变成了常量,它的值必须在定义的时候初始化,并且后面的代码不能对其进行修改,它的命名应该全部都是大写。当一个方法被修饰成final的之后,这个方法在继承中是不能够被进行覆盖的。当一个类被修饰成final的之后,这个类不能再有子类。

final 关键字可以应用于类,以指示不能扩展该类(不能有子类)。 final 关键字可以应用于方法,以指示不能重写任何子类中的方法。

<2>final用于对象应用时,final使应用恒定不变。一旦引用被初始化指向一个对象,就无法再把它指向另一个对象。

<3>final方法:一是把方法锁定,以防止继承类修改它的含义,二是确保继承中使方法行为保持不变,并且不会被覆盖。类中所有的private方法都隐式地指定为是final。 
<4>final参数:对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,以为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句的对象变量,当你在方法中不需要改变作为参数的变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法。 
<5>final类:当将某个类的整体定义为final时,就表明了该类不允许被继承。

解释:最后,终于,不可更改地 
用法:在异常处理机制当中,它的作用就像是人吃饭一样,必须得做的,不论有异常还是没有异常都要执行的代码就可以放到finally块当中去。finally块,必须要配合try块一起使用,不能单独使用,也不能直接和catch块一起使用。 
finally 关键字用来定义始终在 try-catch-finally 语句中执行的块。finally 块通常包含清理代码,用在部分执行 try 块后恢复正常运行。

用法:用来让一个类实现一个接口的关键字,实现接口的这个类必须实现接口里面所有的方法。 

最后,终于,不可更改地

在异常处理机制当中,它的作用就像是人吃饭一样,必须得做的,不论有

异常还是没有异常都要执行的代码就可以放到

不能单独使用,也不能直接和

块通常包含清理代码,用在部分执行

解释:接口,界面 
用法:它本质上是一个类,一个完全抽象的类,里面没有任何实现的方法。它不是用来继承的,是用来实现的。某个类如果实现了接口就必须要实现接口里面的所有方法。并且接口是不能用来实例化的,它也是不能通过new关键字获得对象。 
interface 关键字用来声明新的 Java 接口,接口是方法的集合。 接口是 Java 语言的一项强大功能。任何类都可声明它实现一个或多个接口,这意味着它实现了在这些接口中所定义的所有方法。 
实现了接口的任何类都必须提供在该接口中的所有方法的实现。 一个类可以实现多个接口。

用法:修饰符的一种,能够用来修饰属性和方法。需要注意的是被修饰的属性和方法,不再属于对象所有,而是属于类,意味着,要访问这些属性和方法不再通过对象而是直接用类名来访问。另外,静态的方法不能够访问非静态属性,非静态的方法能够访问静态的属性。 
static 关键字可以应用于内部类(在另一个类中定义的类)、方法或字段(类的成员变量)。 
通常,static 关键字意味着应用它的实体在声明该实体的类的任何特定实例外部可用。 
static(内部)类可以被其他类实例化和引用(即使它是顶级类)。在上面的-示例-中,另一个类中的代码可以实例化 MyStaticClass 类,方法是用包含它的类名来限定其名称,如 MyClass.MyStaticClass。 
static 字段(类的成员变量)在类的所有实例中只存在一次。可以从类的外部调用 static 方法,而不用首先实例化该类。这样的引用始终包括类名作为方法调用的限定符。在上面的示例中,MyClass 类外部的代码以 MyClass.getNumObjects() 的形式调用 getNumObjects() static 方法。 
通常用于声明可以在类的外部使用的类常量。在引用这样的类常量时需要用类名加以限定。在上面的-示例-中,另一个类可以用 MyClass.MAX_OBJECTS 形式来引用 MAX_OBJECTS 常量。 
1>通常在一个类中定义一个方法为static,就是说无须本类的对象就可以直接调用。 
2>静态变量和静态方法类似。所有此类实例共享此静态变量,也就是说类装载时,只分配一块存储空间,所有此类的对象都可以操控此块存储空间,当然对于final就另当别论了。

3>static定义的变量会优先于任何其他非static变量,不论其出现顺序如何。

 4>static{}着是用来显式的静态变量初始化,这段代码只会初始化一次,且在类被第一次装载时。

5>在涉及到继承的时候,会先初始化父类的static变量,然后是子类的。

 6>通常一个普通类不允许声明为静态的,只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用,而不需要实例一个外部类。

synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。  
 在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变

量的代码放到专门的方法中,

为我们提供了更好的解决办法,

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

用法:transient 关键字可以应用于类的成员变量,以便指出该成员变量不应 在包含它的类实例已序列化时被序列化。 
java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。 
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想    
transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。

用法:volatile 关键字用于表示可以被多个线程异步修改的成员变量。 
volatile 的目标用途是为了确保所有线程所看到的指定变量的值都是相同的。 
Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到主内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。      
而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。   
使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。    
由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

最后,终于,不可更改地

在异常处理机制当中,它的作用就像是人吃饭一样,必须得做的,不论有

异常还是没有异常都要执行的代码就可以放到

不能单独使用,也不能直接和

块通常包含清理代码,用在部分执行

最后,终于,不可更改地

在异常处理机制当中,它的作用就像是人吃饭一样,必须得做的,不论有

异常还是没有异常都要执行的代码就可以放到

不能单独使用,也不能直接和

块通常包含清理代码,用在部分执行

}
  • 含义: 运行 Java 字节码的虚拟机。
  • 目的:针对不同系统的特定实现(Windows,Linux,macOS),使用相同的字节码,它们都会给出相同的结果。使一份程序运行至不同平台。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
如何理解Java字节码

在 Java 中,JVM可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java程序无须重新编译便可在多种不同操作系统的计算机上运行。

Java 程序从源代码到运行一般有下面两步:

  1. 字节码文件 ==> 可执行的机器码
  • JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT 编译器,而JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。
  • JDK 9引入了一种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销。JDK支持分层编译和AOT协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。

Java运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java虚拟机(JVM),Java类库,java命令和其他的一些基础构件。但是,它不能用于创建新程序。

要运行一下 Java 程序的话,只需要安装 JRE 就可以了。如果需要进行一些 Java 编程方面的工作,那么你就需要安装JDK了。但是,这不是绝对的。有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是在应用程序服务器中运行Java程序。那你为什么需要JDK呢?因为应用程序服务器会将 JSP

  • 都是面向对象的语言,都支持封装、继承和多态
  • Java 不提供指针来直接访问内存,程序内存更加安全
  • Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。
  • Java 有自动内存管理机制,不需要程序员手动释放无用内存

3. 接口和抽象类的区别

  • 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。
  • 接口中除了static、final变量,不能有其他变量,而抽象类中则不一定。
  • 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过extends关键字扩展多个接口。
  • 接口方法默认修饰符是public,抽象方法可以有public、protected和default这些修饰符(抽象方法就是为了被重写所以不能使用private关键字修饰!)。
  • 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。

内部方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。

没有对方法进行加同步锁,所以是非线程安全的。
对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。

  • 操作少量的数据: 适用String
  • 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
  • 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer

它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。

  1. 类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
  2. 类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
  • 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
  • Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。


  • 线程创建之后它将处于 NEW(新建) 状态,调用 start() 方法后开始运行,线程这时候处于** READY(可运行)** 状态。可运行状态的线程获得了 cpu 时间片(timeslice)后就处于** RUNNING(运行)** 状态。
  • 当线程执行 wait()方法之后,线程进入 WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将 Java 线程置于TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到** BLOCKED(阻塞)** 状态。线程在执行 Runnable 的run()方法之后将会进入到 TERMINATED(终止) 状态。
  • LinkedList: 底层使用的是 双向链表 数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。)
  • ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e) 方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element) )时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。
  • LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。
  1. 是否支持快速随机访问(快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index) 方法))

具有快速随机访问主要看是否实现了 RandomAccess 接口,但是源码 RandomAccess 接口中什么都没有定义。所以, RandomAccess 接口是一个标识, 标识实现这个接口的类具有随机访问功能。

    • ArrayList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。
    • 链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。
  • ArrayList的空间浪费主要体现在在list列表的结尾会预留一定的容量空间。
  • LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。
  • HashMap 是非线程安全的, 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。
  • HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。
  • JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。
  1. 初始容量大小和每次扩充容量大小的不同
  • 创建时如果不指定容量初始值:
    • HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。
    • Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。
  • 创建时如果给定了容量初始值:
    • HashMap 会将其扩充为2的幂次方大小(HashMap 中的tableSizeFor()方法保证,下面给出了源代码)。也就是说 HashMap 总是使用2的幂作为哈希表的大小,后面会介绍到为什么是2的幂次方。
    • Hashtable 会直接使用你给定的大小。

关于详细分析HashMap 可见:

11. 如何理解分析Java内存区域

Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。

      用于记录当前线程执行的位置 (唯一一个不会出现OutOfMemoryError的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。) Java 方法执行的内存模型、编译器可知的各种数据类型。 虚拟机使用到的 Native 方法服务。
      存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。 是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  • 两者最主要的区别在于:sleep 方法没有释放锁,而 wait 方法释放了锁 。
  • 两者都可以暂停线程的执行。
  • sleep()是线程线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复,或者可以使用wait(long timeout)超时后线程会自动苏醒;wait()是Object的方法,调用会放弃对象锁,进入等待队列,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。
  • Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
}

我要回帖

更多关于 java关键字的用法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信