Java错题集(十四)

目录

以下代码段执行后的输出结果为

java语言的下面几种数组复制方法中,哪个效率最高?

在 myjsp.jsp 中,关于下面的代码说法错误的是: (  )   

下面代码的输出是什么?

关于ThreadLocal类 以下说法正确的是

下面程序的输出是:()

使用mvc模式设计的web应用程序具有以下优点,除了?

Java数据库连接库JDBC用到哪种设计模式?

关于Java和C/C++的比较,下列哪个描述是错误的?

关于volatile关键字,下列描述不正确的是?

JVM内存不包含如下哪个部分( )

以下哪些继承自 Collection 接口()

事务隔离级别是由谁实现的?

计算机所能处理的最小的数据项称为()

顺序执行下列程序语句后,则b的值是()

下面有关forward和redirect的描述,正确的是() ?

下列那些方法是线程安全的(所调用的方法都存在)


以下代码段执行后的输出结果为

public class Test {
    public static void main(String args[]) {
        int x = -5;
        int y = -12;
        System.out.println(y % x);
    }
}

正确答案: D   你的答案: D (正确)

-1
2
1
-2

来源:https://www.nowcoder.com/questionTerminal/7b4ec6887dc04af992ce10dadfb532bb

Y(被除数) % X(除数)

当除数与被除数的符号相同时,取余和取模的结果是完全相同的; 当除数与被除数的符号不相同时结果不同

具体说,取余结果的符号与被除数相同取模结果的符号与除数相同

1.取余 rem(3,2)=1 rem(-3,-2)=-1 rem(3,-2)=1 rem(-3,2)=-1

2.取模 mod(3,2)=1 mod(-3,-2)=-1 mod(3,-2)=-1 mod(-3,2)=1

 

java语言的下面几种数组复制方法中,哪个效率最高?

正确答案: B   你的答案: D (错误)

for 循环逐一复制
System.arraycopy
Array.copyOf
使用clone方法

来源:https://www.nowcoder.com/questionTerminal/e7c2d52c9cf0476bbba6aae6713dd303

总结: 

(1)从速度上看:System.arraycopy > clone > Arrays.copyOf > for 
(2)for的速度之所以最慢是因为下标表示法每次都从起点开始寻位到指定下标处(现代编译器应该对其有进行优化,改为指针),另外就是它每一次循环都要判断一次是否达到数组最大长度和进行一次额外的记录下标值的加法运算。 
(3)查看Arrays.copyOf的源码可以发现,它其实本质上是调用了System.arraycopy。之所以时间差距比较大,是因为很大一部分开销全花在了Math.min函数上了。

public static byte[] copyOf(byte[] original, int newLength) { 
    byte[] copy = new byte[newLength];
    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); 
    return copy;
}

(4)查看System.arraycopy的源码,可以发现它实质上是通过Jni调用本地方法,及c/c++已经编译成机器码的方法,所以快。

public static native void arraycopy(Object src, int srcPos,
                                    Object dest, int destPos, int length);

(5)native方法,但并未手写,需要JNI转换

 

在 myjsp.jsp 中,关于下面的代码说法错误的是: (  )   

<%@ page language="java" import="java.util.*" errorPage="error.jsp" isErrorPage="false" %> 

正确答案: A   你的答案: C (错误)

该页面可以使用 exception 对象
该页面发生异常会转向 error.jsp
存在 errorPage 属性时,isErrorPage 是默认为 false
error.jsp 页面一定要有isErrorPage 属性且值为 true

来源:https://www.nowcoder.com/questionTerminal/b07dfbf3f5d7428aacb7387f48084030

exception是JSP九大内置对象之一,其实例代表其他页面的异常和错误。

只有当页面是错误处理页面时,即isErroePage为 true时,该对象才可以使用。

对于C项,errorPage的实质就是JSP的异常处理机制,发生异常时才会跳转到 errorPage指定的页面,没必要给errorPage再设置一个errorPage。

所以当errorPage属性存在时, isErrorPage属性值为false

 

下面代码的输出是什么?

public class Base
{
    private String baseName = "base";
    public Base()
    {
        callName();
    }

    public void callName()
    {
        System. out. println(baseName);
    }

    static class Sub extends Base
    {
        private String baseName = "sub";
        public void callName()
        {
            System. out. println (baseName) ;
        }
    }
    public static void main(String[] args)
    {
        Base b = new Sub();
    }
}

正确答案: A   你的答案: B (错误)

null
sub
base

来源:https://www.nowcoder.com/questionTerminal/c2bfb1512dfa4a7eab773a5871a52402

 new Sub()在创造派生类的过程中首先创建基类对象然后才能创建派生类

创建基类即默认调用Base()方法,在方法中调用callName()方法,由于派生类中存在此方法,则被调用的callName()方法是派生类中的方法此时派生类还未构造所以变量baseName的值为null
 

《Thinking in JAVA》201页提到,如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为static

对于这种说法,我尝试着在A包下面建了一个类X,并在其内部声明了一个静态内部类Y(也叫嵌套类),然后同样是在A包下面,我新建了一个类B,然后在这个类中引用前面那个类Y,发现可以直接引用说明X与Y的确没有联系(虽然引用的时候需要用X.Y的方式引用,不过貌似好像就这点联系了。)

如果Y没有声明为static,那么是无法在B中引用Y的。其实说了这么多,总结来讲,就是static的作用是相当于建立了2个类在工作目录下的确也是生成了2个class文件,既然是2个类,那么这两个类的关系就是单纯的继承关系了。

 

关于ThreadLocal类 以下说法正确的是

正确答案: D E   你的答案: A B C D E (错误)

ThreadLocal继承自Thread
ThreadLocal实现了Runnable接口
ThreadLocal重要作用在于多线程间的数据共享
ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本
ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏

来源:https://www.nowcoder.com/questionTerminal/b82e4a85a66e4dc488a5ab49094976e9

1、ThreadLocal的类声明:

public class ThreadLocal<T>

可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。

2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝每个线程都拥有了自己独立的一个变量

所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。

由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,

变量被彻底封闭在每个访问的线程中。所以E对。

3、ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本

 static class ThreadLocalMap {

 

        static class Entry extends WeakReference<ThreadLocal> {

            /** The value associated with this ThreadLocal. */

            Object value;

 

            Entry(ThreadLocal k, Object v) {

                super(k);

                value = v;

            }

        }

 

        /**

         * The table, resized as necessary.

         * table.length MUST always be a power of two.

         */

        private Entry[] table;

}

所以D对。

 

下面程序的输出是:()

String x="fmn";
x.toUpperCase();
String y=x.replace('f','F');
y=y+"wxy";
System.out.println(y);

正确答案: D   你的答案: D (正确)

FmNwxy
fmnwxy
wxyfmn
Fmnwxy

来源:https://www.nowcoder.com/questionTerminal/caa9ea2063624a04afc91df682bb4729

String x="fmn";  “fmn”是在常量池里的不可变对象。

x.toUpperCase();   在堆中new一个"FMN"对象,但无任何引用指向它。

String y=x.replace('f','F'); 在堆中 new一个"Fmn"对象,y指向它。

y=y+"wxy"; 在堆中 重新new一个"Fmnwxy"对象, 修改y指向,现在y指向它。

 

使用mvc模式设计的web应用程序具有以下优点,除了?

正确答案: D   你的答案: C (错误)

可维护行强
可扩展性强
代码重复少
大大减少代码量

来源:https://www.nowcoder.com/questionTerminal/940d9dd9a582442090b42443f8883f5e


MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
MVC只是将分管不同功能的逻辑代码进行了隔离,增强了可维护和可扩展性,增强代码复用性,因此可以减少代码重复。但是不保证减少代码量,多层次的调用模式还有可能增加代码量

 

Java数据库连接库JDBC用到哪种设计模式?

正确答案: B   你的答案: A (错误)

生成器
桥接模式
抽象工厂
单例模式

来源:https://www.nowcoder.com/questionTerminal/134a62da02d34bc6a7ff309af3fbb76f

JDBC提供两套接口,一个面向数据库厂商,一个面向JDBC使用者。

桥接模式:

定义将抽象部分与它的实现部分分离,使它们都可以独立地变化。

意图 :将抽象与实现解耦。

桥接模式所涉及的角色
1.  Abstraction :定义抽象接口,拥有一个Implementor类型的对象引用
2.  RefinedAbstraction :扩展Abstraction中的接口定义
3.  Implementor :是具体实现的接口,Implementor和RefinedAbstraction接口并不一定完全一致,实际上这两个接口可以完全不一样Implementor提供具体操作方法,而Abstraction提供更高层次的调用
4.  ConcreteImplementor :实现Implementor接口,给出具体实现

Jdk中的桥接模式:JDBC
JDBC连接 数据库 的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不动,原因就是JDBC提供了统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了

 

关于Java和C/C++的比较,下列哪个描述是错误的?

正确答案: C D   你的答案: D (错误)

Java不支持指针,C/C++支持
Java程序不需要显式地关心内存释放,而C/C++需要
Java和C++一样,是纯编译型语言,因此它们的class都是在编译时静态联编(static binding)的
Java数组、字符串不可能溢出,C/C++数组、字符串则有可能溢出边界

来源:https://www.nowcoder.com/questionTerminal/b6f55c8749764ed2876f76a84c4c46a4

Java和C++的区别:

1.Java是解释型语言,所谓的解释型语言,就是源码会先经过一次编译,成为中间码,中间码再被解释器解释成机器码。对于Java而言,中间码就是字节码(.class),而解释器在JVM中内置了。

2. C++是编译型语言,所谓编译型语言,就是源码一次编译,直接在编译的过程中链接了,形成了机器码。

3. C++比Java执行速度快,但是Java可以利用JVM跨平台。

4. Java是纯面向对象的语言,所有代码(包括函数、变量)都必须在类中定义。而C++中还有面向过程的东西,比如是全局变量和全局函数。

5. C++中有指针,Java中没有,但是有引用。

6. C++支持多继承,Java中类都是单继承的。但是继承都有传递性,同时Java中的接口是多继承,类对接口的实现也是多实现。

7. C++中,开发需要自己去管理内存,但是Java中JVM有自己的GC机制,虽然有自己的GC机制,但是也会出现OOM和内存泄漏的问题。C++中有析构函数,Java中Object的finalize方法

8. C++运算符可以重载,但是Java中不可以。同时C++中支持强制自动转型,Java中不行,会出现ClassCastException(类型不匹配)。

 

关于volatile关键字,下列描述不正确的是?

正确答案: B D   你的答案: B C (错误)

用volatile修饰的变量,每次更新对其他线程都是立即可见的。
对volatile变量的操作是原子性的。
对volatile变量的操作不会造成阻塞。
不依赖其他锁机制,多线程环境下的计数器可用volatile实现。

来源:https://www.nowcoder.com/questionTerminal/3f6c5287a9fa4d0baa162e44970a343d

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

2)禁止进行指令重排序。

volatile只提供了保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值——每次都会从内存中读取。

而对该变量的修改,volatile并不提供原子性的保证。

由于及时更新,很可能导致另一线程访问最新变量值,无法跳出循环的情况

多线程下计数器必须使用锁保护。

由于有些时候对 volatile的操作,不会被保存,说明不会造成阻塞。不可用与多线程环境下的计数器。

 

JVM内存不包含如下哪个部分( )

正确答案: D   你的答案: C (错误)

Stacks
PC寄存器
Heap
Heap Frame

来源:https://www.nowcoder.com/questionTerminal/04c442aaf1e14bf9819075cc1f29d899

JVM内存五大区域:左边私有,右边共享

 

 

事务隔离级别是由谁实现的?

正确答案: C   你的答案: B (错误)

Java应用程序
Hibernate
数据库系统
JDBC驱动程序

来源:https://www.nowcoder.com/questionTerminal/ce23bb5a36b54849a05f11187eacb23c


A,我们写java程序的时候只是设定事物的隔离级别,而不是去实现它

B,Hibernate是一个java的数据持久化框架,方便数据库的访问

C,事物隔离级别由数据库系统实现,是数据库系统本身的一个功能

D,JDBC是java database connector,也就是java访问数据库的驱动

 

计算机所能处理的最小的数据项称为()

正确答案: A   你的答案: B (错误)

字节
双字

来源:https://www.nowcoder.com/questionTerminal/fd9860e9c28e4b1dbbe024ee1b590671

位<字节<字<双字

 

顺序执行下列程序语句后,则b的值是()

String a="Hello";

String b=a.substring(0,2);

 

正确答案: C   你的答案: B (错误)

Hello
Hel
He
null

substring    方法将返回一个包含从    start    到最后(不包含  end )的子字符串的字符串。

 

下面有关forward和redirect的描述,正确的是() ?

正确答案: B C D   你的答案: B C (错误)

forward是服务器将控制权转交给另外一个内部服务器对象,由新的对象来全权负责响应用户的请求
执行forward时,浏览器不知道服务器发送的内容是从何处来,浏览器地址栏中还是原来的地址
执行redirect时,服务器端告诉浏览器重新去请求地址
forward是内部重定向,redirect是外部重定向
redirect默认将产生301 Permanently moved的HTTP响应

来源:https://www.nowcoder.com/questionTerminal/e14e58a3d78346be9540a3fbefd62ee3

1.从地址栏显示来说

forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.

redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

 

2.从数据共享来说

forward:转发页面和转发到的页面可以共享request里面的数据.

redirect:不能共享数据.

 

3.从运用地方来说

forward:一般用于用户登陆的时候,根据角色转发到相应的模块.

redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.

 

4.从效率来说

forward:高.

redirect:低.

 

下列那些方法是线程安全的(所调用的方法都存在)

正确答案: A C D   你的答案: C D (错误)

A.
public class MyServlet implements Servlet {
    public void service (ServletRequest req, ServletResponse resp) {
        BigInteger I = extractFromRequest(req);
        encodeIntoResponse(resp,factors);
    }
}


B.
public class MyServlet implements Servlet {
    private long count =0;
    public long getCount() {
        return count;
    }
    public void service (ServletRequest req, ServletResponse resp) {
        BigInteger I = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        count ++;
        encodeIntoResponse(resp,factors);
    }
}

C.
public class MyClass {
    private int value;
    public synchronized int get() {
        return value;
    }
    public synchronized void set (int value) {
        this.value = value;
    }
}

D.
public class Factorizer implements Servlet {
    private volatile MyCache cache = new MyCache(null,null);
    public void service(ServletRequest req, ServletResponse resp) {
    BigInteger i = extractFromRequest(req);
    BigInteger[] factors = cache.getFactors(i);
    if (factors == null) {
        factors = factor(i);
        cache = new MyCache(i,factors);
    }
    encodeIntoResponse(resp,factors);
}

来源:https://www.nowcoder.com/questionTerminal/2d312b47ce1b4921a301db97c1eb4caa

这几个类都没有类属性,不存在共享资源,为了满足题目的意思,应该是多线程情况下使用同一个对象,以达到使成员成为共享资源的目的;

A:没有成员(没有共享资源),线程安全

B:假设存在线程1和线程2,count初始值为0,当线程1执行count++中count+1(此时未写回最终计算值),这时线程2执行count++中读取count,发生数据错误,导致线程1线程2的结果都为1,而不是线程1的结果为1,线程2的结果为2,线程不安全;

C:成员私有,对成员的set get方法都加重量级锁,线程安全;

D:volatile有两个作用:可见性(volatile变量的改变能使其他线程立即可见,但它不是线程安全的,参考B)和禁止重排序;这里是可见性的应用,类中方法对volatile修饰的变量只有赋值,线程安全.


版权声明:本文为qq_45839708原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。