JAVA练习(错题)汇总
-
在java中重写方法应遵循规则的包括()
A 访问修饰符的限制一定要大于被重写方法的访问修饰符
B 可以有不同的访问修饰符
C 参数列表必须完全与被重写的方法相同
D 必须具有不同的参数列表
正确答案: BC
解析:方法的重写两同两小一大原则:
方法名相同,参数类型相同。
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。
- java8中,下面哪个类用到了解决哈希冲突的开放定址法()
A LinkedHashSet
B HashMap
C ThreadLocal
D TreeMap
正确答案: C
解析:在ThreadLocal中,并没实现Map接口。在ThreadLoalMap中,也是初始化一个大小为16的Entry数组table,Entry节点对象用来保存每一个key-value键值对,这里的key永远都是ThreadLocal对象,通过ThreadLocal对象的set方法,结果把ThreadLocal对象自己当做key,放进了ThreadLoalMap中。
注意,ThreadLoalMap的Entry是继承WeakReference,和HashMap很大的区别是,Entry中没有next字段,所以不存在链表的情况。
当遇到哈希冲突时,ThreadLocalMap是怎样解决的:
每个ThreadLocal对象都有一个hash值threadLocalHashCode 每初始化一个ThreadLocal对象,hash值就增加一个固定的HASH_INCREMENT(0x61c88647)大小
在插入过程中,根据ThreadLocal对象的hash值,定位到table中的位置i,过程如下 1、如果当前位置是空的,那么正好,就初始化一个Entry对象放在位置i上 2、位置i已有对象,如果这个Entry对象的key正好是即将设置的key,那么覆盖value 3、位置i的对象,和即将设置的key没关系,那么只能找下一个空位置
这样的话,在get时,也会根据ThreadLocal对象的hash值,定位到table中的位置,然后判断该位置Entry对象中的key是否和get的key一致,如果不一致,就判断下一个位置
可以发现,set和get如果冲突严重的话,效率很低,因为ThreadLoalMap是Thread的一个属性,所以即使在自己的代码中控制了设置的元素个数,但还是不能控制其它代码的行为。
- 有关线程的叙述正确的是()
A 可以获得对任何对象的互斥锁定
B 通过继承Thread类或实现Runnable接口,可以获得对类中方法的互斥锁定
C 线程通过使用synchronized关键字可获得对象的互斥锁定
D 线程调度算法是平台独立的
正确答案: CD
解析:A选项,没有访问权限的对象是无法锁定的。
B选项,前半句是线程的创建方式,,后面讲锁定,题意混乱。
C选项,对。
D选项,线程调度分为协同式调度和抢占式调度,Java使用的是抢占式调度,也就是每个线程将由操作系统来分配执行时间,线程的切换不由线程本身来决定(协同式调度)。这就是平台独立的原因。
- java语言中的数组元素下标总是从0开始,下标可以是整数或整型表达式。()
A 正确
B 错误
正确答案: A
解析:就像平常数组遍历时:
for(int i=0;i<10;i++){
a[i+1]=a[i]
}
其中这里面的i+1就是整型表达式,或比如a[5+3]就是a[8].
- What will be printed when you execute the following code?
class C {
C() {
System.out.print("C");
}
}
class A {
C c = new C();
A() {
this("A");
System.out.print("A");
}
A(String s) {
System.out.print(s);
}
}
class Test extends A {
Test() {
super("B");
System.out.print("B");
}
public static void main(String[] args) {
new Test();
}
}
A BB
B CBB
C BAB
D None of the above
正确答案:B
解析:初始化过程是这样的:
首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化。
然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化。
其次,初始化父类的普通成员变量和代码块,再执行父类的构造方法。
最后,初始化子类的普通成员变量和代码块,再执行子类的构造方法。
本题:(1),初始化父类的普通成员变量和代码块,执行C c = new C();输出C
(2),super("B"),表示调用父类的有参构造方法,输出B
(3),System.out.print("B")............最终结果CBB
- 下面有关servlet service描述错误的是?
A 不管是post还是get方法提交过来的连接,都会在service中处理
B doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的
C service()是在javax.servlet.Servlet接口中定义的
D service判断请求类型,决定是调用doGet还是doPost方法
答案:B
解析:servlet图示:
注意关键点:(servlet生命周期:https://www.cnblogs.com/lingz/p/10031309.html)
(1)service方法是在servlet的生命周期的服务期,默认在HttpServlet类中实现,根据HTTP请求(GET,POST等方法),将请求分发给doGet,doPost等方法实现。
(2)GenericServlet抽象类给出了设计servlet的一些骨架,定义了servlet生命周期还有一些得到的名字,配置,初始化参数的方法,其设计的是和应用层协议无关的。doget和dopost与Http协议有关,是在javax.servlet.http.HttpServlet中实现的。
(3)doGet和doPost方法在HttpServlet类中实现,GenericServlet中实现了service()
(4)常说所有的请求都先由service方法处理,而javax.servlet.GenericServlet接口实现了javax.servlet.Servlet接口,且javax.servlet.http.HttpServlet是javax.servlet.GenericServlet的子类。只有先定义好了的service方法才可以处理所有的请求。
- jre 判断程序是否执行结束的标准是()
A 所有的前台线程执行完毕
B 所有的后台线程执行完毕
C 所有的线程执行完毕
D 和以上都无关
答案:A
解析:main()函数即主函数,是一个前台线程,前台线程中必须执行完成的,而后台线程则是java中所有前台结束后结束,不管有没有完成,后台线程主要用与内存分配等方面。
(1)后台线程不会阻止进程的终止。属于某个进程的所有前台进程都终止后,该进程就会终止。所有剩余的后台线程都会停止且不会完成。
(2)可以在任何时候将前台进程改为后台进程,方式是设置Thread.IsBackground属性。
(3)不管是前台线程还是后台线程,如果线程内出现了异常,都会导致进程的终止。
(4)托管线程池中的线程,使用new Thread方式创建的线程默认都是前台线程。
说明:应用程序的主线程以及Thread构造的线程都默认为前台线程。
- 在JAVA中,下面关于String类和StringBuffer类的描述正确的是那一个?
A StringBuffer类的对象调用toString()方法将返回String类型的结果
B 两个类都有append()方法
C 可以直接将字符串“test”赋值给声明的String类和StringBuffer类的变量
D 两个类的实例的值都能够被改变
正确答案:A
解析:关于A选项,要注意,StringBuffer类的对象调用toString()方法将返回String类型的结果,这是对的。StringBuffer类的对象调用toString()方法将转换为String类型,这是错的。StringBuffer对象toString()方法之后该对象还是StringBuffer对象,只不过该方法的返回值是个String对象,如图所示:
B选项,String类型中没有append方法。
C选项,可以直接将字符串“test”复制给声明的String类和StringBuffer类的变量 引用类型只有String可以直接复制,其他的都要new出来
D选项,String类是不可改变的,首先被设计成一个final类,不可继承,value这个变量是private的,并且没有提供setValue,等公共方法来修改这些值,所以在String类的外部无法修改String,也就是说一旦初始化就不能修改,并且在String类的外部不能访问这个成员。此外,value这个变量是final的,也就是说在String类内部,一旦这个值初始化了,也不能被改变。
- 下面有关 java 类加载器,说法正确的是?()
A 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的
B 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。
C 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类
D tomcat 为每个 App 创建一个 Loader,里面保存着此 WebApp 的 ClassLoader。需要加载 WebApp 下的类时,就取出 ClassLoader 来使用
正确答案: ABCD
解析:类的加载是由类的加载器完成的,类加载起包括:根加载器(BootStrap),扩展加载器(Extension),系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java2(JDK1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的BootStrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会像Java程序提供对BootStrap的引用。下面是关于几个类加载器的说明:
1.BootStrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar)
2.Extension: 从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是BootStrap。
3.system class loader: 又叫应用类加载器,其父类是Extension.它是应用最广泛的类加载器。它从classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。
4. 用户自定义类加载器:java.lang.ClassLoader 的子类。
今日毕,未完待续!!!