面试准备系列——Java基础技术篇(3)/关键字

本文深入解析Java中的关键概念,包括变量命名规则、final与finally及finalize的区别、static的作用、switch使用技巧、volatile特性、instanceof用法及strictfp的影响。通过详细示例帮助读者掌握这些核心知识点。
摘要由CSDN通过智能技术生成

1.变量命名有哪些规则

在Java语言中,变量名、函数名、数组名统称为标识符,Java语言规定标识符只能由数字(0~9)、字母(a ~ z,A ~ Z)、下画线(_ )和$组成,并且**标识符的第一个字符必须是字母、下画线或 $ **。 此外,标识符也 不能包含空白字符( 换行符、空格和制表符)。
以下标识符都是非法的。
char: char 是Java语言的一个数据类型,是保留字,不能作为标识符,其他如int、float
等与之类似。
number of book:标识符中不能有空格。
3com:标识符不能以数字开头。
a*b: * 不能作为标识符的字符。

值得注意的是,在Java语言中,变量名是区分大小写的,例如Count与count被认为是两个不同的标识符,而非相同的标识符。

常见题型:
在这里插入图片描述

2.(重点)final、finally以及finalize有什么区别

final 、finally和finalize的区别如下:

  1. final用于声明属性、方法和类,分别表示属性不可变方法不可覆盖和类不可被继承(不能再派生出新的子类)。

final属性:被final修饰的变量不可变。由于不可变有两重含义:一是引用不可变;二是对象不可变,那么final指的是哪一种含义呢?举例说明:
在这里插入图片描述

从以上的例子中可以看出,final指的是引用的不可变性,即它只能指向初始时指向的那个对象,而不关心指向对象内容的变化。所以,被final修饰的变量必须被初始化。
一般可以通过以下几种方式对其进行初始化:
①在定义的时候初始化。
②final成员变量可以在初始化块中初始化,但不可在静态初始化块中初始化。
③静态final成员变量可以在静态初始化块中初始化,但不可在初始化块中初始化。
④在类的构造器中初始化,但静态final成员变量不可
以在构造函数中初始化。

final方法:当一个方法声明为final时,该方法不允许任何子类重写这个方法,但子类仍然可以使用这个方法。另外,还有一种被称为inline (内联)的机制,当调用一个被声明为final的方法时,直接将方法主体插人到调用处,而不是进行方法调用(类似于C ++中的inline),这样做能提高程序的效率。

final参数:用来表示这个参数在这个函数内部不允许被修改。

final类:当一个类被声明为final时,此类不能被继承,所有方法都不能被重写但这并不表示final 类的成员变量也是不可改变的,要想做到final 类的成员变量不可改变,必须给成员变量增加final 修饰。值得注意的是, 一个类不能既被声明为abstract,又被声明为final。

  1. finally 作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定被执行,经常被用在需要释放资源的情况下。

  2. finalize 是Object类的一个方法,在垃圾回收器执行时会调用被回收对象的finalize( )方法,可以覆盖此方法来实现对其他资源的回收,例如关闭文件等。需要注意的是,一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize( )方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

常见题型:
在这里插入图片描述

3.(重点)static关键字有什么作用

static关键字主要有两种作用:
第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关
第二,实现某个方法或属性与类而不是对象关联在一起,也就是说,在不创建对象的情况下就可以通过类来直接调用方法或使用类的属性。
具体而言,在Java语言中,static 主要有4种使用情况:成员变量、成员方法、代码块和内部类

(1) static成员变量
虽然Java语言中没有全局的概念,但可以通过static关键字来达到全局的效果。Java 类提供了两种类型的变量:用static关键字修饰的静态变量和不用static关键字修饰的实例变量。静态变量属于类,在内存中只有一个复制(所有实例都指向同一个内存地址),只要静态变量所在的类被加载,这个静态变量就会被分配空间,因此就可以被使用了。对静态变量的引用有两种方式,分别为“类.静态变量”和“对象.静态变量”。

实例变量属于对象,只有对象被创建后,实例变量才会被分配空间,才能被使用,它在内存中存在多个复制。只能用“对象.实例变量”的方式来引用。以下是静态变量与实例变量的使用示例。
在这里插入图片描述
运行结果:
在这里插入图片描述
从上例可以看出,静态变量只有一个,被类拥有,所有对象都共享这个静态变量,而实例对象是与具体对象相关的。需要注意的是,与C ++语言不同的是,在Java语言中,不能在方法体中定义static 变量。

(2) static 成员方法
与变量类似,Java 类同时也提供了static 方法与非static 方法。static方法是类的方法,不需要创建对象就可以被调用,而非static方法是对象的方法,只有对象被创建出来后才可以被使用。

static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法,因为当static方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用哪个对象的方法。同理,static方法也不能访问非static类型的变量。

static一个很重要的用途是实现单例模式。单例模式的特点是该类只能有一个实例,为了实现这一功能,必须隐藏类的构造函数,即把构造函数声明为private, 并提供-一个创建对象的方法,由于构造对象被声明为private,外界无法直接创建这个类型的对象,只能通过该类提供的方法来获取类的对象,要达到这样的目的只能把创建对象的方法声明为static,程序示例如下:

	/**
     * 饿汉模式
     */
    static class Singleton1{
        private static Singleton1 instance = new Singleton1();
        private Singleton1(){}
        public static Singleton1 getInstance(){
            return instance;
        }
    }

    /**
     * 懒汉模式
     */
    static class Singleton2{
        private static Singleton2 instance = null;
        private Singleton2(){}
        public synchronized static Singleton2 getInstance(){
            if (instance == null) {
                instance = new Singleton2();
            }
            return instance;
        }
    }

用public修饰的static变量和方法本质上都是全局的,若在static变量前用private修饰,则表示这个变量可以在类的静态代码块或者类的其他静态成员方法中使用,但是不能在其他类中通过类名来直接引用。

(3) static 代码块
static代码块(静态代码块)在类中是独立于成员变量和成员函数的代码块的。它不在任何一个方法体内,JVM在加载类时会执行static 代码块,如果有多个static代码块,JVM将会按顺序来执行。static 代码块经常被用来初始化静态变量。需要注意的是,这些static代码块只会被执行一次,示例如下:
在这里插入图片描述
(4) static 内部类
static内部类是指被声明为static的内部类,它可以不依赖于外部类实例对象而被实例化,而通常的内部类需要在外部类实例化后才能实例化。静态内部类不能与外部类有相同的名字,不能访问外部类的普通成员变量,只能访问外部类中的静态成员和静态方法(包括私有类型),示例如下:
在这里插入图片描述

引申:

  • 1.什么是实例变量?什么是局部变量?什么是类变量?什么是final 变量?
    实例变量:变量归对象所有( 只有在实例化对象后才可以)。每当实例化一个对象时,会创建一个副本并初始化,如果没有显示初始化,那么会初始化一一个默认值。各个对象中的实例变量互不影响。
    局部变量:在方法中定义的变量,在使用前必须初始化。
    类变量:用static可修饰的属性、变量归类所有,只要类被加载,这个变量就可以被使用(类名.变量名)。所有实例化的对象共享类变量。
    final变量:表示这个变量为常量,不能被修改。

  • 2.static 与final结合使用表示什么意思?
    在Java语言中,static 关键字常与final关键字结合使用,用来修饰成员变量与成员方法,有点类似于C/C ++语言中的“全局常量”。对于变量,若使用static final 修饰,则表示一 旦赋值,就不可修改,并且通过类名可以访问。对于方法,若使用static final 修饰,则表示该方法不可覆盖,并且可以通过类名直接访问。

常见题型:
在这里插入图片描述
答案: D。在Java语言中,不能在成员函数内部定义static变量。

4.使用switch时的注意事项

switch语句用于多分支选择,在使用switch (expr) 时,expr 只能是一个枚举常量(内部也是由整型或字符类型实现)或一个整数表达式,其中整数表达式可以是基本类型int或其对应的包装类Integer,当然也包括不同的长度整型,例如short由于byte、short 和char类型的值都能够被隐式地转换为int类型,因此这些类型以及它们对应的包装类型都可以作为switch的表达式。但是,long、 float、 double、 String 类型不能够隐式地转换为int类型,因此它们不能被用作switch的表达式。如果定要使用long、float 或double作为switch 的参数,必须将其强制转换为int型才可以,例如,以下对switch中参数的使用就是非法的。
在这里插入图片描述
另外,与switch对应的是case语句,case 语句之后可以是直接的常量数值,例如1、2,也可以是一一个常量计算式,例如1 +2等,还可以是final型的变量( final变量必须是编译时的常量),例如final inta=0,但不能是变量或带有变量的表达式,例如i * 2等。当然更不能是浮点型数例如1.1或者1.2/2等
在这里插入图片描述
随着Java语言的发展,在Java 7中,switch 开始支持String类型了。以下是一段支持String类型的示例代码:
在这里插入图片描述
从本质上来讲,switch对字符串的支持,其实是int类型值的匹配。它的实现原理如下:
通过对case后面的String对象调用hashCode()方法,得到一个int类型的hash值,然后用这个hash值来唯一标识这个case。那么当匹配时,首先调用这个字符串hashCodel()函数,获取一个hash值(int 类型),用这个hash值来匹配所有case,如果没有匹配成功,说明不存在;如果匹配成功了,接着会调用字符串的String. equals( )方法进行匹配。由此可以看出,String 变量不能为null,同时,switch 的case子句中使用的字符串也不能为null。

在使用switch 时,需要注意另外一个问题:一般必须在case语句结尾添加break语句。因为一旦通过switch语句确定了入口点,就会顺序执行后面的代码,直到遇到关键字break。否则,会执行满足这个case之后的其他case的语句而不管case是否匹配,直到switch 结束或者遇到break为止。如果在switch中省略了break语句,那么匹配的case值后的所有情况(包括default情况),都会被执行,示例如下:
在这里插入图片描述

5.volatile有什么作用(更加详细的可以参考第10章多线程篇章)

在用Java语言编写的程序中,有时为了提高程序的运行效率,编译器会自动对其进行优化,把经常被访问的变量缓存起来,程序在读取这个变量时有可能会直接从缓存(例如寄存器)中来读取这个值,而不会去内存中读取。这样做的一个好处是提高了程序的运行效率,但当遇到多线程编程时,变量的值可能因为别的线程而改变了,而该缓存的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致,例如,在本次线程内,当读取一个变量时,为提高存取速度,会先把变量读取到一个缓存中,当以后再取变量值时,就直接从缓存中取值,当变量值在本线程里改变时,会同时把变量的新值复制到该缓存中,以便保持一致。

volatile是一个类型修饰符(typespecifier),它是被设计用来修饰被不同线程访问和修改的变量。被volatile类型定义的变量,系统每次用到它时都是直接从对应的内存当中提取,而不会利用缓存。在使用了volatile修饰成员变量后,所有线程在任何时候所看到变量的值都是相同的。下面给出一个使用volatile 的示例。
在这里插入图片描述
以上代码示例是用来停止线程最常用的一种方法, 如果boolean类型的变量flag没有被声明为volatile,那么,当这个线程的run方法在判断flag值时,使用的有可能是缓存中的值,此时就不能及时地获取其他线程对flag所做的操作,因此会导致线程不能及时地停止。

需要注意的是,由于volatile不能保证操作的原子性,因此,一般情况下volatile不能代替sychronized。此外,使用volatile会阻止编译器对代码的优化,因此会降低程序的执行效率。所以,除非迫不得已,否则,能不使用volatile就尽量不要使用volatile。

6.instanceof有什么作用

instanceof是Java语言中的一一个二元运算符,它的作用是判断一个引用类型的变量所指向的对象是否是-一个类(或接口、抽象类、父类)的实例,即它左边的对象是否是它右边的类的实例该运算符返回boolean类型的数据。

常见的用法为: result = object instanceof class。如果object是class的-一个实例,那么instanceof运算符返回true;如果object 不是class的一个实例,或者object 是null,那么instanceof运算符返回false。

举例说明:
在这里插入图片描述
在这里插入图片描述

7.strictfp有什么作用

关键字strictfp是strict float point 的缩写,指的是精确浮点,它用来确保浮点数运算的准确性。JVM在执行浮点数运算时,如果没有指定strictfp关键字,此时计算结果可能会不精确,而且计算结果在不同平台或厂商的虚拟机.上会有不同的结果,导致意想不到的错误。而一旦使用了strictfp 来声明一个类、接口或者方法,那么在所声明的范围内,Java 编译器以及运行环境会完全依照IEEE二进制浮点数算术标准( IEEE 754)来执行,在这个关键字声明的范围内所有浮点数的计算都是精确的。需要注意的是,当一个类被strictfp修饰时,所有方法都会自动被strictfp修饰。因此,strictfp 可以保证浮点数运算的精确性,而且在不同的硬件平台上会有一致的运行结果。下例给出了strictfp 修饰类的使用方法:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值