基本语法
字符型常量和字符串常量的区别?
- 形式 : 字符常量是单引号引起的一个字符,字符串常量是双引号引起的 0 个或若干个字符。
- 含义 : 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)。
- 占内存大小: 字符常量只占 2 个字节; 字符串常量占若干个字节。
(注意: char 在 Java 中占两个字节)
标识符和关键字的区别是什么?
在我们编写程序的时候,需要大量地为程序、类、变量、方法等取名字,于是就有了 标识符 。简单来说, 标识符就是一个名字 。
有一些标识符,Java 语言已经赋予了其特殊的含义,只能用于特定的地方,这些特殊的标识符就是 关键字 。简单来说,关键字是被赋予特殊含义的标识符。比如,在我们的日常生活中,如果我们想要开一家店,则要给这个店起一个名字,起的这个“名字”就叫标识符。但是我们店的名字不能叫“警察局”,因为“警察局”这个名字已经被赋予了特殊的含义,而“警察局”就是我们日常生活中的关键字。
Tips:所有的关键字都是小写的,在 IDE 中会以特殊颜色显示。
default
这个关键字很特殊,既属于程序控制,也可以在接口中定义默认方法。
- 在程序控制中,当在
switch
中匹配不到任何情况时,可以使用default
来编写默认匹配的情况。- 当接口提供一个默认实现的方法,并且不强制实现类重写此方法。如果当一个实现类实现了多个接口,多个接口里都有相同的默认方法时,实现类必须重写该默认方法,不然实现类不知道继承哪一个接口的默认方法。如果子类继承父类,父类中有b方法,该子类同时实现的接口中也有b方法(被
default
修饰),那么子类会继承父类的b方法而不是继承接口中的b方法
方法
静态方法为什么不能调用非静态成员?
这个需要结合 JVM 的相关知识,主要原因如下:
- 静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
- 在类的非静态成员不存在的时候静态成员就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。
静态方法和实例方法有何不同?
1、调用方式
一般不建议使用 对象.方法名
的方式来调用静态方法。这种方式非常容易造成混淆,静态方法不属于类的某个对象而是属于这个类。建议使用 类名.方法名
的方式来调用静态方法。
2、访问类成员是否存在限制
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。
重载和重写的区别?
重载
发生在同一个类中(或者父类和子类之间),方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
Java 允许重载任何方法, 而不只是构造器方法。
重写
-
方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
-
如果父类方法访问修饰符为
private/final
则子类就不能重写该方法。 -
如果父类方法访问修饰符为
static
则方法能够被继承,但是不能被重写。如果能被重写,违背了多态性。多态性就是依赖继承和重写
。我们通过下面这个例子来证明一下
public class DEMO{ public static void main(String[] args){ father f = new son(); f.show(); f.method(); } } class father{ static void show(){ System.out.println("父类中的静态方法"); } void method(){ System.out.println("父类中的一般方法"); } } class son extends father{ static void show(){ System.out.println("子类中的静态方法"); } void method(){ System.out.println("子类中的一般方法"); } }
输出:
父类中的静态方法 子类中的一般方法
答案: 多态性在运行时期绑定,根据父类对象引用的实际类型来进行获取,而静态方法不是在运行期绑定的,它早在编译期就绑定了,所以不存在多态性。
-
构造方法无法被重写
⭐️ 关于 重写的返回值类型 这里需要额外多说明一下:如果方法的返回类型是 void 和基本数据类型,则返回值重写时不可修改。但是如果方法的返回值是引用类型,重写时是可以返回该引用类型的子类的。
什么是可变长参数?
从 Java5 开始,Java 支持定义可变长参数,所谓可变长参数就是允许在调用方法时传入不定长度的参数。就如
public static void method1(String... args) {
//......
}
另外,可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数。
public static void method2(String arg1, String... args) {
//......
}
遇到方法重载的情况怎么办呢?会优先匹配固定参数还是可变参数的方法呢?
答案是会优先匹配固定参数的方法,因为固定参数的方法匹配度更高。
我们通过下面这个例子来证明一下。
public class VariableLengthArgument {
public static void printVariable(String... args) {
for (String s : args) {
System.out.println(s);
}
}
public static void printVariable(String arg1, String arg2) {
System.out.println(arg1 + arg2);
}
public static void main(String[] args) {
printVariable("a", "b");
printVariable("a", "b", "c", "d");
}
}
输出:
ab
a
b
c
d
另外,Java 的可变参数编译后实际会被转换成一个数组,我们看编译后生成的 class
文件就可以看出来了。
public class VariableLengthArgument {
public static void printVariable(String... args) {
String[] var1 = args;
int var2 = args.length;
for(int var3 = 0; var3 < var2; ++var3) {
String s = var1[var3];
System.out.println(s);
}
}
// ......
}