【Java面试】---常用关键字及修饰符

来源:互联网 发布:excel数据分析列联表 编辑:程序博客网 时间:2024/04/30 10:58

我把常用关键字分为1,访问限制修饰。2,其它类,方法,变量修饰符。3,调用类型关键字。4工具类型的关键字

访问限制修饰符

这里写图片描述

访问限制修饰符对内部类和外部类不同的支持

  • 对于外部类来说,只有两种修饰,public和默认(default),因为外部类放在包中,只有两种可能,包可见和包不可见。外部类只能用public, abstract 和 final 修饰,因为外部类放在包中,只有两种可能,包可见和包不可见(2种访问权限)

  • 对于内部类来说,可以用所有的修饰,因为内部类放在外部类中,与成员变量的地位一致,所以有四种可能。内部类则可以用 修饰成员变量的修饰符修饰内部类,比如 private,static, protected 修饰外部类能用的也可用,4种访问权限)。

类,方法,变量修饰符

修饰符类型的关键字

abstract和static,final是互斥的,static和final是可以连用的而且abstract不能用private、static、synchronized、native、final访问修饰符修饰。

abstract修饰符(修饰类,方法)

  1. 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象类

  2. 没有抽象构造方法,没有抽象静态方法。 static 和 abstract不能连用

  3. 抽象类中可以有非抽象的构造方法,创建子类的实例时可能会调用这些构造方法。

  4. 抽象类及抽象方法不能被final和private修饰符修饰。final和abstract 不能连用,同样private和abstract不能连用(抽象方法就是被用来实现的)。

  5. 抽象类不能被实例化。因为抽象类可能含有没有方法体的抽象方法

final修饰符(修饰类,变量,方法)

final的基本特性

final具有不可改变的含义,它可以修饰非抽象类,非抽象成员方法和变量

  1. 用final修饰的类不能被继承,没有子类。

  2. 用final修饰的方法不能被子类的方法覆盖(重写)

  3. 用final修饰的变量表示常量,只能被赋一次值必须被显式初始化。但如果final修饰的是引用,它只关心引用的不可变,不关心引用指向的对象的变化

  4. private修饰的方法默认为是final方法,因而不能被子类的方法覆盖。

虽说final的方法不能被覆盖,但以下这种情况可以写一样的:

class Car extends Vehicle{    public static void main (String[] args)    {        new  Car(). run();    }    private final void run()    {        System. out. println ("Car");    }}class Vehicle{    private final void run()    {        System. out. println("Vehicle");    }}

首先final声明的方法是不能被覆盖的,但是这里并不错误,因为方法是private的,也就是子类没有继承父类的run方法,因此子类的run方法跟父类的run方法无关,并不是覆盖但这里如果是public修饰符就会报编译错误

final修饰变量

1,final修饰的成员变量为基本数据类型是,在赋值之后无法改变。当final修饰的成员变量为引用数据类型时,在赋值后其指向地址无法改变,但是对象内容还是可以改变的

2,final修饰的成员变量在赋值时可以有三种方式。
(1)在声明时直接赋值。(2)在构造器中赋值(静态的不可以)。(3)在初始代码块中进行赋值(静态final只能在静态块,动态final只能在构造块)。

3,因为java允许将数据成员声明为final,却不赋初值。但是,blank final必须在使用之前初始化

final,finally,finalize的区别

  • final用于声明属性,类,方法,分别表示属性不可变(基本类型的不可变,引用类型的引用不可变,对象可变),类不可被继承,方法不可被覆盖

  • finally作为异常处理的一部分,只能用于tyr/catch语句中,并且附带一个语句块,表示这段语句一定要执行,经常被用在需要释放资源的情况下,例如文件的关闭,删除临时文件。

  • finalize是Object类的一个方法,在垃圾回收器执行时会调用被回收对象的finalize方法。需要注意的是如果要回收该对象,首先该对象会调用它的finalize方法,在执行期间,如果它能逃逸,就可以逃逸,如果不能,那么在下一次垃圾回收动作发生时该对象被回收。(二次标记)

static修饰符(修饰变量,方法和类)

static基本特性

static修饰的变量可以先不初始化。

  1. 静态变量在内存中只有一个拷贝,在类的所有实例中共享
  2. 在静态方法中不能直接访问实例方法和实例变量,需要new一个实例来访问
  3. 在静态方法中不能使用this和super关键字。
  4. 静态方法不能被abstract修饰
  5. 静态方法和静态变量都可以通过类名直接被访问。
  6. 当类被加载时,静态代码块只被执行一次。类中不同的静态代码块按它们在类中出现的顺序被依次执行
  7. public static void main(String args[]) {} 程序入口方法,可以被final修饰,也可以被synchronized修饰

static修饰类

如果一个类要被声明为static的,只有一种情况,就是静态内部类。如果在外部类声明为static,程序会编译都不会过。

在一番调查后个人总结出了3点关于内部类和静态内部类(俗称:内嵌类)

  • 静态内部类跟静态方法一样,只能访问静态的成员变量和方法,不能访问非静态的方法和属性,但是普通内部类可以访问任意外部类的成员变量和方法

  • 静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。

  • 静态内部类可以单独初始化

native关键字(修饰方法)

native是方法修饰符。Native方法是由另外一种语言(如c/c++,FORTRAN,汇编)实现的本地方法。

因为在外部实现了方法,所以在java代码中,就不需要实现了,定义navtive方法时,并不提供实现体,因为其实现体是用非Java语言在外面实现的。有点类似于接口方法。

Native可以和其他一些修饰符连用,但是abstract方法和Interface里的方法不能用native来修饰。因为native暗示这个方法是有实现体的,而abstract却显式指明了这个方法没有实现体。

调用类型关键字

super关键字

super关键字基本特性

  • 在类的构造方法中,通过super语句调用这个类的父类的构造方法。在构造方法中,super语句必须作为构造方法的第一条语句。

  • 在子类中访问父类的被屏蔽的方法和属性

  • 在构造方法中,super语句必须作为构造方法的第一条语句。

  • 只能在构造方法或实例方法内使用super关键字。 super关键字与类的特定实例相关

super关键字使用场景

1.在子类构造方法中调用父类的构造方法

2.访问父类中被覆盖的同名变量或者方法(而不是父类的被限制访问的私有方法和属性例如private或有些时候可能是default的,例如父类子类不在一个包)

说明:当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类变量覆盖同名父类变量时,可以使用super.成员变量名引用父类成员变量。同时,若子类的成员方法覆盖了父类的成员方法时,也可以使用super.方法名(参数列表)的方式访问父类的方法。

super关键字只能指代直接父类,不能指代父类的父类。

this关键字

this关键字用来指向当前实例对象

通常用于:成员变量和局部变量重名 的时候需要用this来区分成员变量和局部变量,当成员变量和局部变量不能区别时用优先就近的原则。

工具类型关键字

instanceof关键字

它的作用是判断一个引用类型的变量所指向的实例是否是一个类(接口,抽象类,父类)的实例

常见用法:result = object instanceof class返回一个boolean类型的值

package test;class Base{}class Child extends Base{}class Grandchild extends Child{}class TT {}public class Singleton{    public static void main(String[] args) {        Grandchild g = new Grandchild();        if (g instanceof Base) {            System.out.println("TRUE");        }else{            System.out.println("FALSE");        }        if (g instanceof Child) {            System.out.println("TRUE");        }else{            System.out.println("FALSE");        }    }}

也可以判断自己父类的父类是不是满足

switch关键字

switch关键字基本特性

switch语句用于多分支选择,使用switch(expr)时,expr只能是一个枚举常量(内部是整型或字符类型)或一个整数表达式。

  • 其中整数表达式可以是基本类型int(byte,short,char)其对应的包装类

  • 如果要用long,float,double,必须强制转为int才可以

  • String类型在jdk1.7支持(先对字符串里的String值调用hashcode()获取一个int类型的hash值,然后遍历所有case里字符串对应的hash值进行匹配,如果没匹配成功,则说明不存在,如果匹配成功,则接着调用字符串的equals操作进行匹配)equals的范围小于hashcode

switch对String的支持

在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型作为条件。在Java7中,呼吁很久的String支持也终于被加上了。

public class StringForSwitch {    public void test_string_switch() {        String result="";          switch ("doctor") {        case "doctor":            result = "doctor";            break;        default:            break;        }    }}

反编译后的,还原成大致的Java的代码如下:

public class StringForSwitch {    public StringForSwitch() {    }    public void test_string_switch() {        String result = "";        String var2 = "doctor";        switch("doctor".hashCode()) {        case -1326477025:            if(var2.equals("doctor")) {                result = "doctor";            }        default:           break;        }    }}

可以看出,字符串类型在switch语句中利用hashcode的值与字符串内容的比较来实现的;但是在case字句中对应的语句块中仍然需要使用String的equals方法来进一步比较字符串的内容,这是因为哈希函数在映射的时候可能存在冲突。

switch关键字使用注意

1,在switch语句中,表达式的值不能是null,否则会在运行时抛出NullPointerException。在case子句中也不能使用null,否则会出现编译错误。

2,case字句的值是不能重复的。对于字符串类型的也一样,但是字符串中可以包含Unicode转义字符。重复值的检查是在Java编译器对Java源代码进行相关的词法转换之后才进行的。也就是说,有些case字句的值虽然在源代码中看起来是不同的,但是经词法转换之后是一样的,就会在成编译错误。比如:“男”和“\u7537”就是一个意思。

原创粉丝点击