Java笔试题整理(三)— 20190319

0319 笔试题整理

1. 一个文件中的字符要写到另一个文件中,首先需要( )。

A.使用标准输出流System.out.println()。

B.建立文件字符输出流。

C.建立文件字符输入流。

D.标准输入流System.in.read()。

【解析】

一个文件中的字符要写到另一个文件中,首先需要读取这个文件,所以要先建立输入流,然后写到另一个文件,这时再建立输出流.

所以要先建立输入流,再建立输出流.

【答案】

选项C

2. 有如下代码:请写出程序的输出结果。

public class Test
{
    public static void main(String[] args)
    {
        int x = 0;
        int y = 0;
        int k = 0;
        for (int z = 0; z < 5; z++) {
            if ((++x > 2) && (++y > 2) && (k++ > 2))
            {
                x++;
                ++y;
                k++;
            }
        }
        System.out.println(x + ”” +y + ”” +k);
    }
}

A.432

B.531

C.421

D.523

【分析】

z=0时候,执行++x > 2,不成立,&&后面就不执行了,此时 x=1,y=0,k=0;

z=1时候,执行++x > 2,还不成立 ,&&后面就不执行了,此时 x=2,y=0,k=0;

z=2时候, 执行++x > 2,成立,继续执行 ++y > 2, 不成立 , &&后面就不执行了, 此时 x=3,y=1,k=0;

z=3时候,执行++x > 2,成立,继续执行++y > 2,不成立 , &&后面就不执行了, 此时 x=4,y=2,k=0;

z=4 时候,执行++x > 2,成立,继续执行 ++y > 2, 成立 , 继续执行k++>2 ,不成立,此时仍没有进入for循环的语句中, 但此时 x=5,y=3,k=1;

z=5时候,不满足条件了,整个循环结束,所以最好打印时候: x=5,y=3,k=1;

【答案】

B选项

3. 运行下面代码,输出的结果是()

class A {
    public A() {
        System.out.println("class A");
    }
    { System.out.println("I'm A class"); } 
    static { System.out.println("class A static"); }
}
public class B extends A {
    public B() {
        System.out.println("class B");
    }
    { System.out.println("I'm B class"); }
    static { System.out.println("class B static"); }
     
    public static void main(String[] args) { 
 new B(); 
 }
}

A. class A static
class B static
I’m A class
class A
I’m B class
class B

B. class A static
I’m A class
class A
class B static
I’m B class
class B

C. class A static
class B static
class A
I’m A class
class B
I’m B class

D. class A static
class A
I’m A class
class B static
class B
I’m B class

【分析】

ava程序初始化的执行顺序:

父类静态变量—>父类静态代码块—>子类静态变量—>子类静态代码块—>父类非静态变量—>父类非静态代码块—>父类构造方法—>子类非静态变量—>子类非静态代码块—>子类构造方法

【答案】

选项A

4. 下面有关servlet中init,service,destroy方法描述错误的是?

A.init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法

B.service()方法处理客户机发出的所有请求

C.destroy()方法标志servlet生命周期的结束

D.servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的

【分析】

init方法: 是在servlet实例创建时调用的方法,用于创建或打开任何与servlet相的资源和初始 化servlet的状态,Servlet规范保证调用init方法前不会处理任何请求

service方法:是servlet真正处理客户端传过来的请求的方法,由web容器调用, 根据HTTP请求方法(GET、POST等),将请求分发到doGet、doPost等方法

destory方法:是在servlet实例被销毁时由web容器调用。Servlet规范确保在destroy方法调用之 前所有请求的处理均完成,需要覆盖destroy方法的情况:释放任何在init方法中 打开的与servlet相关的资源存储servlet的状态

Servlet是线程不安全的,在Servlet类中可能会定义共享的类变量,这样在并发的多线程访问的情况下,不同的线程对成员变量的修改会引发错误。

【答案】

选项D

5. 关于PreparedStatement与Statement描述错误的是()

A.一般而言,PreparedStatement比Statement执行效率更高

B.PreparedStatement会预编译SQL语句

C.Statement每次都会解析/编译SQL,确立并优化数据获取路径

D.Statement执行扫描的结果集比PreparedStatement大

【分析】

PreparedStatement 接口继承 Statement , PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。

作为 Statement 的子类, PreparedStatement 继承了 Statement 的所有功能。三种方法execute,executeQuery 和 executeUpdate 已被更改以使之不再需要参数

【补充】为什么使用PreparedStatement

一 . 代码的可读性和可维护性

虽然用 PreparedStatement 来代替 Statement 会使代码多出几行 , 但这样的代码无论从可读性还是可维护性上来说 . 都比直接用Statement 的代码高很多档次 :

使用Statement:

stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");//stmt 是 Statement 对象实例

使用PreparedStatement:

perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate(); //prestmt 是 PreparedStatement 对象实例

不用我多说 , 对于第一种方法 . 别说其他人去读你的代码 , 就是你自己过一段时间再去读 , 都会觉得伤心 .

二、PreparedStatement 尽最大可能提高性能 .

语句在被 DB 的编译器编译后的执行代码被缓存下来 , 那么下次调用时只要是相同的预编译语句就不需要编译 , 只要将参数直接传入编译过的语句执行代码中 ( 相当于一个涵数 ) 就会得到执行 . 这并不是说只有一个 Connection 中多次执行的预编译语句被缓存 , 而是对于整个 DB 中 , 只要预编译的语句语法和缓存中匹配 . 那么在任何时候就可以不需要再次编译而可以直接执行 . 而 statement 的语句中 , 即使是相同一操作 , 而由于每次操作的数据不同所以使整个语句相匹配的机会极小 , 几乎不太可能匹配 . 比如 :

insert into tb_name (col1,col2) values (‘11’,‘22’);

insert into tb_name (col1,col2) values (‘11’,‘23’);

即使是相同操作但因为数据内容不一样 , 所以整个个语句本身不能匹配 , 没有缓存语句的意义 . 事实是没有数据库会对普通语句编译后的执行代码缓存 .

当然并不是所以预编译语句都一定会被缓存 , 数据库本身会用一种策略 , 比如使用频度等因素来决定什么时候不再缓存已有的预编译结果. 以保存有更多的空间存储新的预编译语句 .

三 . 最重要的一点是极大地提高了安全性 .

即使到目前为止 , 仍有一些人连基本的恶义 SQL 语法都不知道 .

String sql = “select * from tb_name where name= '”+varname+"’ and passwd=’"+varpasswd+"’";

如果我们把 [’ or ‘1’ = '1] 作为 varpasswd 传入进来 . 用户名随意 , 看看会成为什么 ?

select * from tb_name = ’ 随意 ’ and passwd = ‘’ or ‘1’ = ‘1’;

因为 ‘1’=‘1’ 肯定成立 , 所以可以任何通过验证 . 更有甚者 :

把 [’;drop table tb_name;] 作为 varpasswd 传入进来 , 则 :

select * from tb_name = ’ 随意 ’ and passwd = ‘’;drop table tb_name; 有些数据库是不会让你成功的 , 但也有很多数据库就可以使这些语句得到执行 .

而如果你使用预编译语句 . 你传入的任何内容就不会和原来的语句发生任何匹配的关系 . 只要全使用预编译语句 , 你就用不着对传入的数据做任何过虑 . 而如果使用普通的 statement, 有可能要对 drop,; 等做费尽心机的判断和过虑 .

6. 下面有关maven和ant的描述,描述错误的是?

A.Ant 没有正式的约定如一个一般项目的目录结构,你必须明确的告诉 Ant 哪里去找源代码

B.Maven 拥有约定,因为你遵循了约定,它已经知道你的源代码在哪里

C.maven和ant都有“生命周期”的概念,当你输入一个命令后,maven或者ant会执行一系列的有序的步骤,直到到达你指定的生命周期

D.Ant构建文件默认命名为build.xml,Maven默认构建文件为pom.xml

【分析】

Ant和Maven都是基于Java的构建(build)工具。理论上来说,有些类似于(Unix)C中的make ,但没有make的缺陷。Ant是软件构建工具,Maven的定位是软件项目管理和理解工具。
Ant特点
没有一个约定的目录结构,必须明确让ant做什么,什么时候做,然后编译,打包,没有生命周期,必须定义目标及其实现的任务序列,没有集成依赖管理
Maven特点
拥有约定,知道你的代码在哪里,放到哪里去 ›拥有一个生命周期,例如执行 mvn install 就可以自动执行编译,测试,打包等构建过程 只需要定义一个pom.xml,然后把源码放到默认的目录,Maven帮你处理其他事情 ›拥有依赖管理,仓库管理

【答案】

选择C

7. 如何获取ServletContext设置的参数值?

A.context.getParameter()

B.context.getInitParameter()

C.context.getAttribute()

D.context.getRequestDispatcher()

【分析】

getParameter()是获取POST/GET传递的参数值
getInitParameter获取Tomcat的server.xml中设置Context的初始化参数
getAttribute()是获取对象容器中的数据值
getRequestDispatcher是请求转发

【答案】

选项B

8. Test.main() 函数执行后的输出是()

public class Test {  
    public static void main(String [] args){  
        System.out.println(new B().getValue());  
    }  
    static class A{  
        protected int value;  
        public A(int v) {  
            setValue(v);  
        }  
        public void setValue(int value){  
            this.value = value;  
        }  
        public int getValue(){  
            try{  
                value++;  
                return value;  
            } catch(Exception e){  
                System.out.println(e.toString());  
            } finally {  
                this.setValue(value);  
                System.out.println(value);  
            }  
            return value;  
        }  
    }  
    static class B extends A{  
        public B() {  
            super(5);  
            setValue(getValue() - 3);  
        }  
        public void setValue(int value){  
            super.setValue(2 * value);  
        }  
    }  
}  

A.11 17 34

B.22 74 74

C.6 7 7

D.22 34 17

【分析】

首先,super()函数指的是调用父类的构造方法

new B()

执行B的构造函数,第一行是super(5);

此时执行的是A的构造函数,A的构造函数调用的是setValue()方法,由于B重写了A的这个方法,

所以!!!执行的是B的 setValue()方法。

即传入的参数是2*5=10

此时,因为super,所以调用的是父类的 setValue()方法,即value=10

第一行执行完毕。

第二行是 setValue(getValue()-3);

B没有getValue()方法,故执行父类的此方法,

try返回的是value=10+1=11,保存在临时栈中

finally中调用this的方法,这个this指的是B的对象,又重写,故就是B的 setValue()方法

value=2*11=22,第一个打印到屏幕上的数字

接下来参数 getValue()-3=11-3=8

传入B的 setValue()方法

此时value=2*8=16

至此,new B()执行结束

new B(). getValue()

B没有 getValue(),故执行A的 getValue()

try返回16+1=17,保存到临时栈中

finally调用B的 setValue()方法

value=17*2=34,第二个打印到屏幕上面的数字

最后主函数打印返回值,也就是try保存到临时栈的17

【答案】

选择D

9.对于下面的代码,下面为true的是

Integer i = 42;
Long l = 42l;
Double d = 42.0;

A.(i == l)

B.(i == d)

C.(l == d)

D.i.equals(d)

E.d.equals(l)

F.i.equals(l)

G.l.equals(42L)

【分析】

包装类的“==”运算在不遇到算术运算的情况下不会自动拆箱

包装类的equals()方法不处理数据转型

【知识点】

1、基本型和基本型封装型进行“==”运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;

int a = 220;
Integer b = 220;
System.out.println(a==b);//true

2、两个Integer类型进行“==”比较, 如果其值在-128至127 ,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关,这里不进行赘述。

Integer c=3;
Integer h=3;
Integer e=321;
Integer f=321;
System.out.println(c==h);//true
System.out.println(e==f);//false

3、两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true。

Integer a=1;
Integer b=2;
Integer c=3;
System.out.println(c.equals(a+b));//true

4、基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较。

int i=1;
int j = 2;
Integer c=3;
System.out.println(c.equals(i+j));//true

【答案】

选择D

10. 有关线程的叙述正确的是()

A.可以获得对任何对象的互斥锁定

B.通过继承Thread类或实现Runnable接口,可以获得对类中方法的互斥锁定

C.线程通过使用synchronized关键字可获得对象的互斥锁定

D.线程调度算法是平台独立的

【分析】

A,“任何对象”锁定,太绝对了,你能锁住你没有权限访问的对象吗?

B,前半句话讲的是创建线程的方式,后半句讲的是锁定,驴头不对马嘴。

C,正确。

D,线程调度分为协同式调度和抢占式调度,Java使用的是抢占式调度,也就是每个线程将由操作系统来分配执行时间,线程的切换不由线程本身来决定(协同式调度)。这就是平台独立的原因。

【答案】

以上,选CD

11. 下列描述正确的是( )

A.类不可以多继承而接口可以多实现

B.抽象类自身可以定义成员而接口不可以

C.抽象类和接口都不能被实例化

D.一个类可以有多个基类和多个基接口

【分析】

1.java支持单继承,却可以实现多个接口。a对d错
2.接口没有构造方法,所以不能实例化,抽象类有构造方法,但是不是用来实例化的,是用来初始化的。c对
3.抽象类可以定义普通成员变量而接口不可以,但是抽象类和接口都可以定义静态成员变量,只是接口的静态成员变量要用static final public 来修饰。b错

【答案】

AC

12. jre 判断程序是否执行结束的标准是()

A.所有的前台线程执行完毕

B.所有的后台线程执行完毕

C.所有的线程执行完毕

D.和以上都无关

【分析】

其实这个题,就是在说守护线程和非守护(用户)线程的问题。后台线程就是守护线程,前台线程就是用户线程。

守护线程:是指在程序运行时在后台提供一种通用服务的线程,这种线程并不是必须的。同时守护线程的线程优先级都很低的。JVM中的GC线程就是一个守护线程,只要JVM启动,GC线程就启动了。

用户线程和守护线程几乎没有什么区别,唯一的区别就在于,如果用户线程都已经退出了,只剩下了守护线程,那么JVM直接就退出了。

【答案】

选项A

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值