导语
Java 面试题集2021版
Java基础部分三
- 37、abstract 的method 是否可同时是static,是否可同时是native,是否可同时是synchronized?
- 38、什么是内部类?Static Nested Class 和Inner Class 的不同
- 39、内部类可以引用它的包含类的成员吗?有没有什么限制?
- 40、Anonymous Inner Class(匿名内部类)是否可以extends(继承)其他类,是否可以implement(实现)interface(接口)?
- 41、JDK中那些类是不能被继承的?
- 42、Java中是否有过程和函数?
- 43、String 是最基本的数据类型吗?
- 44、String s = "Hello";s = s+"World!";这两行代码执行之后,原始的String对象中的内容到底有没有发生变化?
- 45、String 类是否可以继承?
- 46、String s = new String("nihui");创建了几个String Object?二者之间有什么区别?
37、abstract 的method 是否可同时是static,是否可同时是native,是否可同时是synchronized?
abstract 的Method不可以是static 的,因为抽象的方法是要被子类实现的,而static与子类无关。
native 方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在这被子类实现的问题,所以它也不能是抽象的,不能与abstract 混合使用。在Java中有有很多这样的方法。
关于synchronized与abstract 合用的问题,在平时的开发中没有用到过这种情况,因为对于一个抽象类,如果其中有一个方法被加上了synchronized方法那就说明所有继承了这个类的其他子类都会实现这个方法,这个时候就有一个问题,就是在程序执行过程中,所有遇见这个方法的地方,都会被加锁。这回导致的问题就是内存泄漏的问题。另外对于这个锁,应该指的是具体的某个一锁,而不是泛泛的所有锁。
38、什么是内部类?Static Nested Class 和Inner Class 的不同
内部类就是在一个类的内部定义的类,内部类中不能定义静态成员,内部类可以直接访问外部类中的成员变量,内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中,例如
public class Outer{
int out = 0;
public void method(){
Inner1 inner1 = new Inner1();
public class Inner2{
public method(){
out = 3;
}
}
}
public class Inner1{
}
}
在方法体外面定义的内部类的访问类型可以是public,protected,默认的,private等4种类型,这就好像类中定义的成员变量有4中访问类型一样,它们决定了这个内部类的定义对其它类是否可见;对于这种情况,我们可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象。
在方法内部定义的内部类不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用final或者abstract修饰符。这种内部类对其它类是不可见的其它无法引用这种内部类,这种内部类创建实例对象可以传递给其它访问类,这种内部类必须是先定义,然后在使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理是一样的,这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符
在方法体内部还可以采用如下的语法来创建一种匿名内部类,即定义某一接口或类的子类的同时,还可以创建该子类的实例对象,无需为该子类定义名称:
public class Outer{
public void start(){
new Thread(
new Runable(){
pbulic void run(){
}
}
).start();
}
}
最后,在方法外部定义的内部类前面可以加上static关键字,从而成为Static Nested Class ,它不再具有内部类的特性,所以,从狭义上来讲,它不是内部类。Static Nested Class 与普通类在运行时的行为和功能没有什么区别,只是在编程引用的时候有些区别,它可以定义成public,protected,默认的,private 等多种类型,而普通类只能定义成public和默认的这两种类型,在外面引用Static Nested Class 类的名称为“外部类名.内部类名”。在外部不需要创建外部类的实例对象,就可以直接通过上面这种方式进行对象创建。
由于Static Nested Class 不依赖于外部类的实例对象,所以Static Nested Class 能访问外部类的非static成员变量。当在外部类中访问Static Nested Class 时,可以直接使用Static Nested Class 的名称,而不需要加上外部类的名字,在Static Nested Class 中也可以直接引用外部类的static 成员变量,不需要加上外部类的名称。
在静态方法中定义的内部类也是Static Nested Class ,这时候不能在类前面加上static关键字,静态方法中的Static Nested Class 与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须要加上final关键字。
39、内部类可以引用它的包含类的成员吗?有没有什么限制?
完全可以。如果不是静态内部类,那就没有什么限制!
如果你把静态嵌套类当做内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员,例如,下面的代码
class Outer{
static int x;
static class Inner{
void test(){
syso();
}
}
}
40、Anonymous Inner Class(匿名内部类)是否可以extends(继承)其他类,是否可以implement(实现)interface(接口)?
可以继承其他类或实现其他接口,不仅是可以的,而且是必须的!
41、JDK中那些类是不能被继承的?
不能继承的类是用final关键字修饰的类。一般比较基本的类型或者是为了防止扩展类无意间破坏原来的方法的实现的类型应该都是final的,在JDK中System、String、StringBuffer等这些都是不能被继承的。
42、Java中是否有过程和函数?
在Java中可以存在过程和函数。在Java中,对于程序的各种功能实现,都是通过方法实现的;而方法在运行的时候 ,就被称为是过程。Java中的函数有main(),时间函数等等。
43、String 是最基本的数据类型吗?
Java 中包含8种基本数据类型Byte、int、char、long、float、double、boolean和short
java.lang.String 是一个引用类型,在Java中大的分类还可以分为基本数据类型,和引用类型,所有基本数据类型的封装类都是引用类型。
44、String s = “Hello”;s = s+“World!”;这两行代码执行之后,原始的String对象中的内容到底有没有发生变化?
没有,原因是String 被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,S原先指向了一个String对象,内容是“Hello”,然后 对S进行了+ 操作,那么S所指向的对象是否发生变化呢?答案是没有,这个时候,S不指向原来那个对象,而是指向了另一个String对象,内容是“HelloWorld!”, 原来那个对象还存在于内存之中,只是S这个引用变量不再指向它了。
通过上面的说明,可以得到一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String 来代表字符串的话会引起很大的内存开销。因为String 对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新对象。并且,这两种类型的对象转换也是十分容易实现的。
同时,如果要使用内容相同的字符串,不必每次都new一个String。例如
public class Demo{
private String s;
public Demo{
s = "Hello World!"
}
}
而不是每次都调用new String() 方法,每次调用构造器,生成新对象,性能低下且内存消耗大,并且也没啥实际的意义,因为String 对象是不可变的,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就是说,多次调用上面的构造器创建多个对象,它们的String 类型属性s都指向同一个对象。
通过上面的分析还可以得出一个结论,对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new 调用构造器,总是会创建一个新的对象,无论内容是否相同。至于为什么要把String类设计成不可变的类,这是因为它的用途决定的。不只是String类型,在Java中还有很多的地方都是不可变的。这个不仅要考虑到性能还要考虑到实用性等问题。
45、String 类是否可以继承?
String类是final类,不可以被继承。
46、String s = new String(“nihui”);创建了几个String Object?二者之间有什么区别?
两个或者一个,“nihui” 对应一个对象,这个对象放在字符串常量缓冲区,常量"nihui" 不管出现多少遍,都是缓冲区中的那一个。new String() 每写一遍,就创建一个新对象,它依据那个常量"nihui" 对象的内容来创建出一个新String 对象。如果以前就使用过"nihui",这个代码就不会创建"nihui",直接从缓冲区获取。