试题汇总
1、下面哪个流类属于面向字符的输入流?(D)
A. BufferedWriter
B. FileInputStream
C. ObjectInputStream
D. InputStreamReader
解析:B,C是面向字节的输入流,不符合题意,A是面向字符的,不过是输出流,D正确,是面向字符的输入流,面向字符的输入流类都是Reader的子类
2、关于对象成员占用内存的说法哪个正确?(B )
同一个类的对象共用同一段内存
同一个类的对象使用不同的内存段,但静态成员共享相同的内存空间
对象的方法不占用内存
以上都不对
解析:当你创建一个新的实例对象时,它会得到一块新的内存空间。但是类中的静态成员变量是所有对象共有的,也就是在一片属于类的存储空间中,被所有对象共有。
静态成员属于类成员,在方法区分配内存,而不是堆。静态变量属于类本身,成员变量属于类的某个实例
3、在 Java 中,属于整数类型变量的是(C)
single
double
byte
char
解析:
Java中的四类八种基本数据类型
第一类:整数类型 byte short int long
第二类:浮点型 float double
第三类:逻辑型 boolean(它只有两个值可取true false)
第四类:字符型 char string
4、执行语句“int a= ’ 2 ’ ”后,a的值是(B )
2
50
49
0
解析:
常用ASCII码值:空格为32;数字0为48;“A”为65;“a”值为97。
记忆:486 597 -> 486 (486 + 111)
5、下列哪些操作会使线程释放锁资源?(BC)
sleep()
wait()
join()
yield()
解析:
1.sleep会使当前线程睡眠指定时间,不释放锁
2.yield会使当前线程重回到可执行状态,等待cpu的调度,不释放锁
3.wait会使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll唤醒时进入可执行状态
4.当前线程调用 某线程.join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁
6、关于运行时常量池,下列哪个说法是正确的(BCD)
运行时常量池大小受栈区大小的影响
运行时常量池大小受方法区大小的影响
存放了编译时期生成的各种字面量
存放编译时期生成的符号引用
解析:
方法区是什么?
方法区是广义上的概念,是一个定义、标准,可以理解为Java中的接口,在Jdk6、7方法区的实现叫永久代;Jdk8之后方法区的实现叫元空间,并从JVM内存中移除,放到了直接内存中;
方法区是被所有方法线程共享的一块内存区域.
运行时常量池是什么?
运行时常量池是每一个类或接口的常量池的运行时表示形式.
具体体现就是在Java编译后生成的.class文件中,会有class常量池,也就是静态的运行时常量池;
运行时常量池存放的位置?
运行时常量池一直是方法区的一部分,在不同版本的JDK中,由于方法区位置的变化,运行时常量池所处的位置也不一样.JDK1.7及之前方法区位于永久代.由于一些原因在JDK1.8之后彻底祛除了永久代,用元空间代替。
运行时常量池存放什么?
存放编译期生成的各种字面量和符号引用;
运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。 此时不再是常量池中的符号地址了,这里换为真实地址。
运行时常量池与字符串常量池?
字符串常量池:在JVM中,为了减少相同的字符串的重复创建,为了达到节省内存的目的。会单独开辟一块内存,用于保存字符串常量,这个内存区域被叫做字符串常量池.
字符串常量池位置?
JDK1.6时字符串常量池,被存放在方法区中(永久代),而到了JDK1.7,因为永久代垃圾回收频率低;而字符串使用频率比较高,不能及时回收字符串,会导致导致永久代内存不足,就被移动到了堆内存中。
以下会产生精度丢失的类型转换是(B )
float a=10
int a=(int)8846.0
byte a=10; int b=-a
double d=100
解析:
精度丢失只会发生在从大范围到小范围的转换
只要int类型的数没有超出(byte,short,char)的表述范围也就是127,可以直接byte a=23
7、执行下列代码的输出结果是(30 )
public class Demo{
public static void main(String args[]){
int num = 10;
System.out.println(test(num));
}
public static int test(int b){
try
{
b += 10;
return b;
}
catch(RuntimeException e)
{
}
catch(Exception e2)
{
}
finally
{
b += 10;
return b;
}
}
}
解析:
如果finally块中有return语句的话,它将覆盖掉函数中其他return语句。
8、下列循环语句序列执行完成后,i的值是(11)
int i;
for(i=2;i<=10;i++){
System.out.println(i);
}
解析:
循环体结束,表达式3执行一次,判断表达式2是否成立,如果成立执行循环体;
9、多态的作用(BC)
隐藏细节
提高可重用性
扩展代码模块
提高编译可靠性
10、下面有关java类加载器,说法正确的是?(ABCD)
引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的
扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。
系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类
tomcat为每个App创建一个Loader,里面保存着此WebApp的ClassLoader。需要加载WebApp下的类时,就取出ClassLoader来使用
解析:
Java中的类加载器
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
引导类加载器(bootstrap class loader):
它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。主要负责jdk_home/lib目录下的核心api 或 -Xbootclasspath 选项指定的jar包装入工作(其中的jdk_home是指配置jdk环境变量是java_home的配置路径,一般是jdk/jre所在目录)。
扩展类加载器(extensions class loader):
它用来加载 Java 的扩展库。Java虚拟机的实现会提供一个扩展库目录,扩展类加载器在此目录里面查找并加载 Java 类,主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。
系统类加载器(system class loader):
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。主要负责CLASSPATH/-Djava.class.path所指的目录下的类与jar包装入工作.
除了系统提供的类加载器以外,开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,从而进行动态加载class文件,以满足一些特殊的需求,这体现java动态实时类装入特性。
除了引导类加载器之外,所有的类加载器都有一个父类加载器,通过getParent()方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。下图中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6oqn9Dk-1650426630969)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220419115724948.png)]
11、在Web应用程序的文件与目录结构中,web.xml是放置在( )中。
WEB-INF目录
12、下面论述正确的是(D)?
如果两个对象的hashcode相同,那么它们作为同一个HashMap的key时,必然返回同样的值
如果a,b的hashcode相同,那么a.equals(b)必须返回true
对于一个类,其所有对象的hashcode必须不同
如果a.equals(b)返回true,那么a,b两个对象的hashcode必须相同
解析:
hashCode()方法和equals()方法的作用其实是一样的,在Java里都是用来对比两个对象是否相等一致。
***那么equals()既然已经能实现比较的功能了,为什么还要hashCode()呢?*因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。
那么hashCode()既然效率这么高为什么还要equals()呢? 因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,
所以我们可以得出:
1.equals()相等的两个对象他们的hashCode()肯定相等,也就是用equals()对比是绝对可靠的。
2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。
所有对于需要大量并且快速的对比的话如果都用equals()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equals(),如果equals()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!
13、Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少 ©.
11 ,-11
11 ,-12
12 ,-11
12 ,-12
解析:
Math类中提供了三个与取整有关的方法:ceil,floor,round,这些方法的作用于它们的英文名称的含义相对应,例如:ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.6)的结果为-11;floor的英文是地板,该方法就表示向下取整,Math.floor(11.6)的结果是11,Math.floor(-11.4)的结果-12;最难掌握的是round方法,他表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果是12,Math.round(-11.5)的结果为-11。
14、如果int x=20, y=5,则语句System.out.println(x+y +“”+(x+y)+y); 的输出结果是(D)
2530
55
2052055
25255
解析:
1)不论有什么运算,小括号的优先级都是最高的,先计算小括号中的运算,得到x+y +“”+25+y
2)任何字符与字符串相加都是字符串,但是是有顺序的,字符串前面的按原来的格式相加,字符串后面的都按字符串相加,得到25+“”+25+5
15、针对jdk1.7,以下哪个不属于JVM堆内存中的区域(B)?
survivor区
常量池
eden区
old区
解析:
堆可以分为两部分:新生代,老年代。
新生代:1/3的堆空间 老年代:2/3的堆空间
而新生代可以细分:8/10的Eden区。2/10的Survivor区
Suivivor又可以细分为From区和To区,各占一半。
常量池属于 PermGen(方法区)
注意:
1.永久代MetaData在jdk1.8之前属于堆,现在属于物理内存,与堆完全隔开了
2.方法区只是逻辑概念,MetaData永久代和元空间是实实在在存在的,不能混为一体,元空间是方法区的具体实现。
16、定义:String s1 = “uml”; String s2 = “uml”; String s3= new String(“uml”); String s4= new String(“uml”);那么,s1==s2;s3 == s4;s1.equals(s3); 判断正确与否
T,F,T
解析:
==:比较两个引用的地址和值
equals:比较两个引用的值
17、transient 变量和下面哪一项有关? (B)
Cloneable
Serializable
Runnable
Comparable
解析:
通常一个类实现序列化方式是实现序列化接口 Serializable
序列化的作用:把数据长久的保存在磁盘中,磁盘和内存是不同的,内存一般在程序运行时占用,数据保存周期短,随程序结束而结束,磁盘可以长久保存数据
transient关键字的作用,在已实现序列化的类中,有的变量不需要保存在磁盘中,就要transient关键字修饰,如银行卡密码等,就这个作用------在已序列化的类中使变量不序列化
18、How should servlet developers handle the HttpServlet’s service() methond when extending HttpServlet?(D)
They should override the service()method in most cases;
They should call the service()method from doGet()or doPost();
They should call the service()method from the init()method;
They should override at least one doXXX()method(such as doPost())
题目的意思是开发者在开发servlet继承HttpServlet时如何处理父类的service方法,一般我们都是不对service方法进行重载 (没有特殊需求的话),而只是重载doGet()之类的doXxx()方法,减少了开发工作量。但如果重载了service方法,doXXX()方法也是 要重载的。即不论是否重载service方法,doXXX()方法都是需要重载的。D说至少需要重载doXXX()方法是对的.
19、下面说法正确的是?(BC)
调用Thread的sleep()方法会释放锁,调用wait()方法不释放锁
一个线程调用yield方法,可以使具有相同优先级线程获得处理器
在Java中,高优先级的可运行的线程会抢占低优先级线程的资源
java中,线程可以调用yield方法使比自己低优先级的线程运行
解析:
yield()让当前正在运行的线程回到可运行状态,以允许具有相同优先级的其他线程获得运行的机会
20、Java是一门支持反射的语言,基于反射为Java提供了丰富的动态性支持,下面关于Java反射的描述,哪些是错误的:( A D F )
Java反射主要涉及的类如Class, Method, Filed,等,他们都在java.lang.reflet包下
通过反射可以动态的实现一个接口,形成一个新的类,并可以用这个类创建对象,调用对象方法
通过反射,可以突破Java语言提供的对象成员、类成员的保护机制,访问一般方式不能访问的成员
Java反射机制提供了字节码修改的技术,可以动态的修剪一个类
Java的反射机制会给内存带来额外的开销。例如对永生堆的要求比不通过反射要求的更多
F、Java反射机制一般会带来效率问题,效率问题主要发生在查找类的方法和字段对象,因此通过缓存需要反射类的字段和方法就能达到与之间调用类的方法和访问类的字段一样的效率
解析:
A Class类在java.lang包
B 动态代理技术可以动态创建一个代理对象,反射不行
C 反射访问私有成员时,Field调用setAccessible可解除访问符限制
D CGLIB实现了字节码修改,反射不行
E 反射会动态创建额外的对象,比如每个成员方法只有一个Method对象作为root,他不胡直接暴露给用户。调用时会返回一个Method的包装类
F 反射带来的效率问题主要是动态解析类,JVM没法对反射代码优化。
21、以下关于java封装的描述中,正确的是:A
封装的主要作用在于对外隐藏内部实现细节,增强程序的安全性
封装的意义不大,因此在编码中尽量不要使用
如果子类继承父类,对于父类中进行封装的方法,子类仍然可以直接调用
只能对一个类中的方法进行封装,不能对属性进行封装
22、下列符号中可以在 java 程序里表示单行注释的是(C )
--
/* ……*/
//
/** ……*/
解析:
1、单行(single-line)–短注释://……
注释格式:/* 注释内容 /
2、块(block)–块注释:/……*/
23、类中的数据域使用private修饰为私有变量,所以任何方法均不能访问它。(错误)
解析:
本类中还是可以的。同时利用反射也可以做到。
24、下面哪个不是Java基本类型?B
short
Boolean
byte
float
解析:
Java数据类型分为两大类:基本数据类型和引用数据类型(抽象数据类型)
基本数据类型(8种 ):
整型:
byte 1字节 8位(0000 0000)
short 2字节
int 4字节
long 8字节
浮点型:
float 4字节
double 8字节
字符型:
char 2字节
布尔型:
boolean 长度有争议(true,false)
基本数据类型对应的包装类型首字符大写,除过int 和 char
int----->Integer
char---->Character
引用数据类型:(内存中的地址)
类,接口,数组
25、下面所示的java代码,运行时,会产生()类型的异常(D)
int Arry_a[] = new int[10];
System.out.println(Arry_a[10]);
ArithmeticException
NullPointException
IOException
ArrayIndexOutOfBoundsException
解析:
定义的数组长度为10,角标即为0-9
26、有程序片段如下,以下表达式结果为 true 的是(B)
Float s=new Float(0.1f);
Float t=new Float(0.1f);
Double u=new Double(0.1);
s==t
s.equals(t)
u.equals(s)
t.equals(u)
解析:
Float类和Double类都重写对于的equals方法,在比较之前都会判断是否同属于Float对象或Double对象,如果不是直接返回false,如果是再继续比较对应的数值大小。
27、关于抽象类与最终类,下列说法错误的是?(D)
抽象类能被继承,最终类只能被实例化。
抽象类和最终类都可以被声明使用
抽象类中可以没有抽象方法,最终类中可以没有最终方法
抽象类和最终类被继承时,方法可以被子类覆盖
解析:
1,抽象类中可以有抽象方法,也可以没有抽象方法。
2,抽象类当然可以被继承,因为它就是用来继承的,
3,继承抽象类,若有抽象方法,则子类必须将其抽象方法实现,
4,抽象类中的非抽象方法可以被重写。
最终类和抽象类正好相反
5,加上final的类就叫最终类,加上final的方法就叫最终方法,
6,最终类中可以有最终方法也可以没有
7,最终类不能有子类,最终方法不能被重写
28、下面有关servlet中init,service,destroy方法描述错误的是?(D)
init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法
service()方法处理客户机发出的所有请求
destroy()方法标志servlet生命周期的结束
servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的
解析:
Servlet是线程不安全的,在Servlet类中可能会定义共享的类变量,这样在并发的多线程访问的情况下,不同的线程对成员变量的修改会引发错误。
29、关于Java语言中的final关键字的使用,下列说法正确的是(C)
在使用final关键字定义的方法里面必须使用final关键字定义变量。
使用final关键字定义变量,必须在变量定义的同时给定变量的具体数值,完成变量初始化。
final关键字可以用来修饰方法,表明此方法不可以被子类重写。
使用final关键字定义变量,必须同时使用static关键字。
解析:
A 选项在 final 定义的方法里,不是必须要用 final 定义变量。
B final 定义的变量,可以在不是必须要在定义的同时完成初始化,也可以在构造方法中完成初始化。
C 正确,final修饰方法,不能被子类重写,但是可以被重载。
D final 定义变量,可以用 static 也可以不用。
30、从以下哪一个选项中可以获得Servlet的初始化参数?(C)
Servlet
ServletContext
ServletConfig
GenericServlet
解析:
ServletContext对象:servlet容器在启动时会加载web应用,并为每个web应用创建唯一的servlet context对象,可以把ServletContext看成是一个Web应用的服务器端组件的共享内存,在ServletContext中可以存放共享数据。ServletContext对象是真正的一个全局对象,凡是web容器中的Servlet都可以访问。
整个web应用只有唯一的一个ServletContext对象
servletConfig对象:用于封装servlet的配置信息。从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对servlet自身有效,一个servlet的ServletConfig对象不能被另一个servlet访问。
31、下列说法正确的是( C)
volatile,synchronized
都可以修改变量,方法以及代码块
volatile,synchronized 在多线程中都会存在阻塞问题
volatile能保证数据的可见性,但不能完全保证数据的原子性,synchronized即保证了数据的可见性也保证了原子性
volatile解决的是变量在多个线程之间的可见性、原子性,而sychroized解决的是多个线程之间访问资源的同步性
解析:
可见性:
可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉。通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。
**可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。**也就是一个线程修改的结果。另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这个操作同样存在线程安全问题。
在 Java 中 volatile、synchronized 和 final 实现可见性。
原子性:
**原子是世界上的最小单位,具有不可分割性。**比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。
在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性。
有序性:
Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。
当一个变量定义为 volatile 之后,将具备两种特性:
1.保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存来完成。
2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。
volatile 性能:
volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。
32、下面程序的结果是(1201)
public class Demo {
public static String sRet = "";
public static void func(int i)
{
try
{
if (i%2==0)
{
throw new Exception();
}
}
catch (Exception e)
{
sRet += "0";
return;
}
finally
{
sRet += "1";
}
sRet += "2";
}
public static void main(String[] args)
{
func(1);
func(2);
System.out.println(sRet);
}
}
解析:
①调用func(1),if不符合,直接进入finally,sRet=“1"
②finally语句中没有返回值,故继续向下执行,sRet=“12”
③调用func(2),if符合,sRet=“120”,此时有返回值!!!
④调用finally语句,sRet=“1201”
⑤因为已经有返回值了,finally之后的语句也不再执行,sRet=“1201”。
33、下列哪个说法是正确的(D)
ConcurrentHashMap使用synchronized关键字保证线程安全
HashMap实现了Collction接口
Array.asList方法返回java.util.ArrayList对象
SimpleDateFormat是线程不安全的
解析:
A、ConcurrentHashMap实际上时 HashTable的升级版,使用segment来分段和管理锁,并不是synchronized;
B、 HashMap实现的接口有:Serializable, Cloneable, Map<K,V> ,没有实现Collction接口
C、Arrays.asList()方法返回的列表是Arrays.ArrayList类型的,并不是java.util.ArrayList;
34、Java数据库连接库JDBC用到哪种设计模式?(B)
生成器
桥接模式
抽象工厂
单例模式
35、socket编程中,以下哪个socket的操作是不属于服务端操作的(C)?
accept
recieve
getInputStream
close
解析:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AbRlX1qP-1650426630976)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220419133937170.png)]
TCP客户端:
1.建立连接套接字,设置Ip和端口监听,socket()
2.建立连接 connect
3.write() 获取网络流对象 发送数据
4.read()获取网络流对象 接收数据
5.关闭套接字
TCP服务器端
1.建立端口监听 socket()
2.绑定指定端口 bind()
3.listen 进行端口监听
4.accept() 阻塞式 直到有客户端访问
5.read()获取客户端发送数据
6.write()发送返回数据
7.close关闭端口监听
36、
static String str0="0123456789";
static String str1="0123456789";
String str2=str1.substring(5);
String str3=new String(str2);
String str4=new String(str3.toCharArray());
str0=null;
假定str0,…,str4后序代码都是只读引用。
Java 7中,以上述代码为基础,在发生过一次FullGC后,上述代码在Heap空间(不包括PermGen)保留的字符数为(15)
解析:
方法区:主要存储结构信息的地方,比如方法体,同时也是存储静态变量,以及静态代码块的区域,构造函数,常量池,接口初始化等等 方法区物理上还是在堆中,是在堆的持久代里面。堆有年轻代 (由一个Eden区和俩个survivor区组成),老年代,持久代。新创建的对象都在年轻代的Eden区,经过一次JC收集后,存活下来的会被复制到survivor区(一个满了,就全部移动到另外一个大的中,但要保证其中一个survivor为空),经过多次JC后,还存活的对象就被移到老年代了。 持久代就是经常说的方法区里面存放类信息,常量池,方法等 static String str0=“0123456789”; static String str1=“0123456789”;是放在方法区里。也就是持久代,题目中已经说了,不包含持久代,所以剩余空间为5+5+5=15.
37、抽象类方法的访问权限默认都是public。( 错误)
解析:
关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default
关于接口
JDK 1.8以前,接口中的方法必须是public的
JDK 1.8时,接口中的方法可以是public的,也可以是default的
JDK 1.9时,接口中的方法可以是private的
38、下列关于包(package)的描述,正确的是(D)
包(package)是Java中描述操作系统对多个源代码文件组织的一种方式。
import语句将所对应的Java源文件拷贝到此处执行。
包(package)是Eclipse组织Java项目特有的一种方式。
定义在同一个包(package)内的类可以不经过import而直接相互使用。
39、对于上面这段代码,以下说法正确的是:(C)
public class Test
{
public int x;
public static void main(String []args)
{
System. out. println("Value is" + x);
}
}
程序会打出 "Value is 0"
程序会抛出 NullPointerException
非静态变量不能够被静态方法引用
编译器会抛出 "possible reference before assignment"的错误
解析:
当类加载时,static静态方法随着类加载而初始化,此时实例对象还未被创建,但是非静态成员变量需要等到实例对象创建才会被初始化,故无法被引用。
40、给出以下代码,请给出结果.(null 42 42)
class Two{
Byte x;
}
class PassO{
public static void main(String[] args){
PassO p=new PassO();
p.start();
}
void start(){
Two t=new Two();
System.out.print(t.x+””);
Two t2=fix(t);
System.out.print(t.x+” ” +t2.x);
}
Two fix(Two tt){
tt.x=42;
return tt;
}
}
解析:
1.注意第二行代码,Byte x;Byte是包装类,不是byte(基本数据类型),因此Byte的默认是null,不是0
2.t是一个引用地址类型,在调用fit(Two tt)函数是,是一个实参到形参的传值,也就是把t的地址赋值给了tt,但是都是指向堆内存中新建的对象,因此当对tt.x和t.x指向是相同的。因此t.x也是42
3.Two t2=fit(t);fit函数返回的还是一个引用地址,这句代码相当于把t(函数里面返回的是tt)的地址赋值给了t2,因此t2.x也是42
41、以下代码段执行后的输出结果为(1,3,2)
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
private static int test() {
int temp = 1;
try {
System.out.println(temp);
return ++temp;
} catch (Exception e) {
System.out.println(temp);
return ++temp;
} finally {
++temp;
System.out.println(temp);
}
}
}
解析:
执行顺序为:
输出try里面的初始temp:1;
temp=2;
保存return里面temp的值:2;
执行finally的语句temp:3,输出temp:3;
返回try中的return语句,返回存在里面的temp的值:2;
输出temp:2。
42、Java语言中,方法的重写(Overriding)和重载(Overloading)是多态性的不同表现。下边哪些说法是对的?(AC)
重写是父类与子类之间多态性的一种表现
重写是一个类中多态性的一种表现
重载是一个类中多态性的一种表现
重载是父类与子类之间多态性的一种表现
解析:
重写(Overriding)是父类与子类之间多态性的一种表现,类的不同实现可以重写父类方法,实现同方法名,同参数,同返回类型,不同的实现。重载(Overloading)最典型的就是一个类的不同构造函数,方法名相同,参数个数不同,返回类型也可以不同,重载是一个类中多态性的一种表现。
43、以下说法错误的是( AB)
final修饰的方法不能被重载
final可以修饰类、接口、抽象类、方法和属性
final修饰的方法也不能被重写
final修饰的属性是常量,不可以修改
解析:
A.final修饰方法后,方法是不可被重写的,因为它已经是“最终形态”了。但不会影响重载
B.final修饰类标志此类不可被继承。如果final可以标志抽象类和接口,抽象类不能继承?接口不准实现?
那还要来什么意义,所以final不能修饰抽象类和接口
C.题目中这个也字就是来误导人的,同A一样解释过了,final修饰的方法不可重写
D.这道题不能太钻牛角尖,final确实是修饰变量,只不过被修饰过的变量不能再变了,既然变量不能再变了我们就可以把它当做常量。
44、下列描述错误的是?(BD)
类只能继承一个父类,但是可以实现多个接口
抽象类自身可以定义成员而接口不可以
抽象类和接口都不能被实例化(忽略匿名内部类)
一个类可以有多个父类和多个基接口
解析:
**A、**java为单继承,多实现。可以实现多个接口。
B、接口允许定义成员,但必须是常量。
C、抽象类和接口类的无法实例化,任何编译器中直接使用new会报错。
D、同A,单继承,多实现。
45、下面哪些类实现或继承了 Collection 接口?(BC)
HashMap
ArrayList
Vector
Iterator
46、不能用来修饰interface的有(ACD )(仅限外部接口)
private
public
protected
static
解析:类、方法、成员变量和局部变量的可用修饰符
修饰符 | 类 | 成员访求 | 构造方法 | 成员变量 | 局部变量 |
---|---|---|---|---|---|
abstract(抽象的) | √ | √ | - | - | - |
static (静态的) | - | √ | - | √ | - |
public(公共的) | √ | √ | √ | √ | - |
protected(受保护的) | √ | √ | √ | - | |
private(私有的) | - | √ | √ | √ | - |
synchronized(同步的) | - | √ | - | - | - |
native(本地的) | - | √ | - | - | - |
transient(暂时的) | - | - | - | √ | - |
volatie(易失的) | - | - | - | √ | - |
final(不要改变的) | √ | √ | - | √ | √ |
47、下面关于volatile的功能说法正确的是哪个(BC)
原子性
有序性
可见性
持久性
解析:
synchronized保证三大性,原子性,有序性,可见性,volatile保证有序性,可见性,不能保证原子性
48、关于volatile关键字,下列描述不正确的是?(BD)
用volatile修饰的变量,每次更新对其他线程都是立即可见的。
对volatile变量的操作是原子性的。
对volatile变量的操作不会造成阻塞。
不依赖其他锁机制,多线程环境下的计数器可用volatile实现。
49、设Tree为已定义的类名,下列语句能正确创建 Tree 对象的是 。(B)
Tree t=new Tree;
Tree t=new Tree();
Tree t=Tree();
Tree t[ ]=new Tree[10];
解析:
D创建的数组对象,不是Tree对象!需要用对象的时候还得再次new,不然直接用数组调用提示空指针
50、关于类的叙述正确的是(B)。
在类中定义的变量称为类的成员变量,在别的类中可以直接使用
局部变量的作用范围仅仅在定义它的方法内,或者是在定义它的控制流块中
使用别的类的方法仅仅需要引用方法的名字即可
只要没有定义不带参数的构造函数,JVM都会为类生成一个默认构造函数
解析:
A,类是一个封装,类的成员只能在类内部使用,外部需要 “对象名.变量名” 来引用。
B,正确,局部变量只在定义它的代码块或者函数内部可见
C,跟类的成员变量一样,需要指定对象才能引用
D,如果类没有构造方法,JVM会生成一个默认构造方法,如果定义了任意类型的构造方法,编译器都不会自动生成构造方法。
51、正则表达式语法中 \d 匹配的是?(A)
数字
非数字
字母
空白字符
解析:
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]'。
\W 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。
52、以下关于 abstract 关键字的说法,正确的是(D)
abstract 可以与final 并列修饰同一个类。
abstract 类中不可以有private的成员。
abstract 类中必须全部是abstract方法。
abstract 方法必须在abstract类或接口中。
53、在基本JAVA类型中,如果不明确指定,整数型的默认是什么类型?带小数的默认是什么类型?(B)
int float
int double
long float
long double
54、执行如下代码段后,变量s1引用的字符串值是( A )。
String s1 = “ABCD”;
String s2 = “1234”;
System.out.println(s1 + s2);
ABCD
1234
ABCD1234
1234ABCD
解析:
因为 String 是不可变类型,是存储在常量字符区的, 所以答案是ABCD。 另外可千万不要选成输出显示的结果
55、DK1.8版本之前,抽象类和接口的区别,以下说法错误的是D
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。
abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface,实现多重继承。接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用。
在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,不过在 interface中一般不定义数据成员),所有的成员方法默认都是 public abstract 类型的。
abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"has-a"关系,interface表示的是"is-a"关系。
解析:
is-a:继承关系 has-a:从属关系 like-a:组合关系
D项: abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。
56、在Java中,以下数据类型中,需要内存最多的是(B)
byte
long
Object
int
解析:
Object 是引用数据类型,只申明而不创建实例,只会在栈内存中开辟空间,默认为空,空占1 bit.
57、下面这条语句一共创建了多少个对象:String s=“welcome”+“to”+360;(1)
解析:
是否大家有没有刷到这类面试题:在执行String s = “Hello”;s = s + " world!";这两行代码后,原始的String对象中的内容到底变了没有?
答案的解析:
没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 “Hello”,然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
…
public Demo {
s = “Initial Value”;
}
…
}
而非
s = new String(“Initial Value”);
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即 StringBuffer。
说说我的看法:字面量的创建是发生在编译期,类似于上述面试题,答案只创建一个对象。
反编译可以看出,在编译阶段已经将各个字段拼接成一个字符串,由于当前内存中没有该拼接的字符串,所以会动态生成一个对象,内容是拼接后的字符串。
58、假如某个JAVA进程的JVM参数配置如下:
-Xms1G -Xmx2G -Xmn500M -XX:MaxPermSize=64M -XX:+UseConcMarkSweepGC -XX:SurvivorRatio=3,
请问eden区最终分配的大小是多少?(C)
64M
500M
300M
100M
解析:
先分析一下里面各个参数的含义:
-Xms:1G , 就是说初始堆大小为1G
-Xmx:2G , 就是说最大堆大小为2G
-Xmn:500M ,就是说年轻代大小是500M(包括一个Eden和两个Survivor)
-XX:MaxPermSize:64M , 就是说设置持久代最大值为64M
-XX:+UseConcMarkSweepGC , 就是说使用使用CMS内存收集算法
-XX:SurvivorRatio=3 , 就是说Eden区与Survivor区的大小比值为3:1:1
题目中所问的Eden区的大小是指年轻代的大小,直接根据-Xmn:500M和-XX:SurvivorRatio=3可以直接计算得出
500M*(3/(3+1+1))
=500M*(3/5)
=500M*0.6
=300M
所以Eden区域的大小为300M。
59、下面代码输出结果是?(-6)
int i = 5;
int j = 10;
System.out.println(i + ~j);
公式-n=n+1可推出n=-n-1,所以~10=-11再加5结果为-6
60、下列Java代码中的变量a、b、c分别在内存的____存储区存放。(堆区、栈区、栈区)
class A {
private String a = “aa”;
public boolean methodB() {
String b = “bb”;
final String c = “cc”;
}
}
解析:
常量池:未经 new 的常量
堆区:成员变量的引用,new 出来的变量
栈区:局部变量的引用
成员变量的引用在堆区,是因为成员变量的所属对象在堆区,所以它也在堆区。
61、java8中,下面哪个类用到了解决哈希冲突的开放定址法(B)
LinkedHashSet
HashMap
ThreadLocal
TreeMap
解析:ThreadLocalMap中使用开放地址法来处理散列冲突,而HashMap中使用的是分离链表法。之所以采用不同的方式主要是因为:在ThreadLocalMap中的散列值分散得十分均匀,很少会出现冲突。并且ThreadLocalMap经常需要清除无用的对象,使用纯数组更加方便。
62、下列说法正确的是(BD)?
我们直接调用Thread对象的run方法会报异常,所以我们应该使用start方法来开启一个线程
一个进程是一个独立的运行环境,可以被看做一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源
synchronized可以解决可见性问题,volatile可以解决原子性问题
ThreadLocal用于创建线程的本地变量,该变量是线程之间不共享的
63、下面的类哪些可以处理Unicode字符? : A B C
InputStreamReader
BufferedReader
Writer
PipedInputStream
解析:
简单地说,字符流是字节流根据字节流所要求的编码集解析获得的
可以理解为字符流=字节流+编码集
所以本题中和字符流有关的类都拥有操作编码集(unicode)的能力。
字节流:
InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
字符流
Reader
|-- InputStreamReader (byte->char 桥梁)
|-- BufferedReader (常用)
Writer
|-- OutputStreamWriter (char->byte 桥梁)
|-- BufferedWriter
|-- PrintWriter (常用)
64、Servlet的生命周期可以分为初始化阶段,运行阶段和销毁阶段三个阶段,以下过程属于初始化阶段是( A C D)。
加载Servlet类及.class对应的数据
创建servletRequest和servletResponse对象
创建ServletConfig对象
创建Servlet对象
解析:
Servlet的生命周期可以分为初始化阶段,运行阶段和销毁阶段三个阶段,以下过程属于初始化阶段是
-
加载Servlet类及.class对应的数据
-
创建ServletConfig对象
-
创建Servlet对象
每一次请求来到容器时,会产生HttpServletRequest与HttpServlceResponse对象,并在调用service()方法时当做参数传入。
在WEB容器启动后,会读取Servlet设置信息,将Servlet类加载并实例化,并为每个Servlet设置信息产生一个ServletConfig对象,而后调用Servlet接口的init()方法,并将产生的ServletConfig对象当作参数传入。
65、以下类型为Final类型的为(BC)
HashMap
StringBuffer
String
Hashtable
解析:
StringBuilder , StringBuffer ,String 都是 final 的,但是为什么StringBuilder , StringBuffer可以进行修改呢,因为不可变包括的是,引用不可变以及对象不可变,而这三个都是属于引用不可变,(也就是地址不要变,里面的内容随心所欲),而StringBuilder , StringBuffer 中都包含右append方法,可对对象中的内容进行增加。
而String a=“123”+new String(“456”);实际上底层是用了一个StringBuffer 进行append;
final修饰的成员变量为基本数据类型时,赋值后无法改变。当final修饰的为引用变量时,在赋值后其指向地址无法改变,但对象内容可以改变。
通过阅读源码可以知道,string与stringbuffer都是通过字符数组实现的。
其中string的字符数组是final修饰的,所以字符数组不可以修改。
stringbuffer的字符数组没有final修饰,所以字符数组可以修改。
string与stringbuffer都是final修饰,只是限制他们所存储的引用地址不可修改。
至于地址所指内容能不能修改,则需要看字符数组可不可以修改。
66、以下代码执行后输出结果为(A )
public class Test
{
public static Test t1 = new Test();
{
System.out.println("blockA");
}
static
{
System.out.println("blockB");
}
public static void main(String[] args)
{
Test t2 = new Test();
}
}
blockAblockBblockA
解析:
静态域:用staitc声明,jvm加载类时执行,仅执行一次
构造代码块:类中直接用{}定义,每一次创建对象时执行。
**执行顺序优先级:静态域,main(),**构造代码块,构造方法。
1 静态域 :首先执行,第一个静态域是一个静态变量 public static Test t1 = new Test(); 创建了Test 对象,会执行构造块代码,所以输出blockA。然后执行第二个静态域(即静态代码块)输出blockB。
2 main():Test t2 = new Test()执行,创建Test类对象,只会执行构造代码块(创建对象时执行),输出blockA。
3 构造代码块只会在创建对象时执行,没创建任何对象了,所以没输出
4 构造函数:使用默认构造函数,没任何输出
67、下列关于异常的说法,正确的是(A)
RuntimeException及其子类的异常可以不做处理
Catch段中的语句,不允许再次出现异常
在方法定义中以throws标识出的异常,在调用该方法中的方法必须处理
程序中所有的可能出现的异常必须在catch中捕获,否则将引起编译错误
解析:在调用此方法的时候 也可以再次申明 以将异常交由更高一级处理
68、一个容器类数据结构,读写平均,使用锁机制保证线程安全。如果要综合提高该数据结构的访问性能,最好的办法是______。C
只对写操作加锁,不对读操作加锁
读操作不加锁,采用copyOnWrite的方式实现写操作
分区段加锁
无法做到
69、下面属于JSP内置对象的是?(ABCD)
out对象
response对象
application对象
page对象
70、以下哪种JAVA的变量表达式使得变量a和变量b具有相同的内存引用地址( )
String a = "hello"; String b = "hello";
Integer a; Integer b = a;
int a = 1; Integer b = new Integer(1);
int a = 1; Integer b = 1;
解析:
内存引用地址,是指栈中存放的地址,来指向堆中的某个位置。
int 是基本类型,数据直接存放在栈中,不存在内存引用地址的说法
A对 指向常量池里的"hello"。
B对 题中没说声明的a是局部变量。
C错 int a =1;并不指向堆中,它只有值,没有引用地址,Integer b =new Integer(1);指向堆中地址为1的位置。
D错 原因同C
71、下列代码输出结果为( )
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal();
Animal b = new Dog();
a.move();
b.move();
b.bark();
}
}
编译错误
解析:
父类型引用指向子类型对象,无法调用只在子类型里定义的方法
72、观察以下代码:(A)
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");
}
}
Car
Vehicle
Compiler error at line 3
Compiler error at line 5
Exception thrown at runtime
解析:
此题的父类方法有private修饰,所以对子类不可见,子类不能覆盖。所以子类方法和父类是两个方法。
扩展:如果父类方法将private改为public 会怎样?
会报错,因为父类方法有final修饰,不能被覆盖。