牛客刷题笔记--(java基础301-400)

301 不考虑反射机制,一个子类显式调用父类的构造器必须用super关键字。( √ )
子类显示调用父类中的构造方法必须使用super关键字;如果子类没有显示调用父类中的构造方法,则系统默认会调用父类中的无参构造方法;若此时父类中没有定义无参构造方法则会报错

java中的super关键词
super用于代表子类的直接父类的特征
super可以访问:
父类的成员变量,成员方法,构造方法
使用super关键词的情况:
在子类中,存在与父类相同的属性和方法,由于访问子类中属性和方法的优先级高于父类,可以通过super关键词来访问父类中的属性和方法
在子类中,可以通过super关键词来显示的调用父类的构造方法
子类的构造方法默认调用父类的无参构造方法,当父类中不存在无参构造方法时,可以同过super来调用父类的有参构造方法来避免编译时错误。

302 在java中,无论在何处调用,使用静态属性必须以类名做前缀。(×)

如果是本类使用,可以直接就用静态变量名。2如果是其他类使用,可以使用类名来调用,也可以创建一个实例对象来调用。3如果静态变量所在的类是静态类,那么不管在本类里或者在其他外部类,都可以直接使用静态变量名。
在静态类里面调用类成员变量,不需要类名前缀、。

303 下面关于Java package的描述,哪个是正确的:(B)

 I. 包不提供将所有类名分区为更易管理的块的机制.
II. 包提供可见性控制机制.
III. 包的一个重要属性是包内定义的所有类都可以通过该包外的代码访问.
IV. 声明为包的一部分的类的.class文件可以存储在多个目录中. 
只有I

只有II

只有III

只有IV

Java 提供了包机制,用于区别类名的命名空间,访问控制。
包名必须与相应的字节码所在的目录结构相吻合。

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
包的作用

1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。

2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。

3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。

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

for 循环逐一复制

System.arraycopy

Array.copyOf

使用clone方法

复制的效率System.arraycopy>clone>Arrays.copyOf>for循环,这个有兴趣自己测试一下就知道了。这里面在System类源码中给出了arraycopy的方法,是native方法,也就是本地方法,肯定是最快的。而Arrays.copyOf(注意是Arrays类,不是Array)的实现,Arrays.copyOf方法中调用的是System.arraycopy方法!,多了一个步骤,肯定就不是最快的

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

305 Thread. sleep()是否会抛出checked exception?(会)

Thread.sleep() 和 Object.wait(),都可以抛出 InterruptedException。这个异常是不能忽略的,因为它是一个检查异常(checked exception)

checked exception:指的是编译时异常,该类异常需要本函数必须处理的,用try和catch处理,或者用throws抛出异常,然后交给调用者去处理异常。
runtime exception:指的是运行时异常,该类异常不必须本函数必须处理,当然也可以处理。
Thread.sleep()抛出的InterruptException属于checked exception;IllegalArgumentException属于Runtime exception;

Thread.sleep()会抛出InterruptedException,这个属于checked exception,也就是编译时异常,我们必须显式的捕获异常而不能继续上外层抛出,因为这个异常需要该线程自己来解决。

306 下列关于JavaBean的说法正确的是:(A)

Java文件与Bean所定义的类名可以不同,但一定要注意区分字母的大小写

在JSP文件中引用Bean,其实就是用语句

被引用的Bean文件的文件名后缀为.java

Bean文件放在任何目录下都可以被引用

(1)懂得将 Bean 放在哪个目录下:在 Resin 中 JavaBean 放在 doc\web-inf\classes 目录 中。
(2)懂得如何使用 JBuilder 定义一个 Bean;其中的语法规范不一定要记住,但要理解
其中的结构。
(3)Java 文件和 Bean所定义的类名一定要相同,并且是大小写敏感。
(4)Bean中要声明公共方法,与 Bean的名字相同。
(5)懂得如何在JSP 文件中引用JavaBean,其实就是jsp:useBean的语句。
(6)一定要紧记Java 是区分大小写的。

A: Bean定义的类名的含义应该是实例化的一个类,在JSP中相当于id,class属性对应的是需要编译的类,在后面用到id的实例化类名 需要区分大小写
B: 是声明了一个Bean 不是引用
C: 引用的文件是web-Inf\class\下的class文件
D: 需要放在web-Inf\class\

307 ResultSet中记录行的第一列索引为?(1)

ResultSet结果集读取数据的方法主要是getXXX() ,他的参数可以使整型表示第几列(是从1开始的),还可以是列名。

Java ResultSet 概论
308 What might cause the current thread to stop or pause executing(ABE)

An InterruptedException is thrown.

The thread executes a wait() call.

The thread constructs a new Thread.

A thread of higher priority becomes ready.

The thread executes a waitforID()call on a MediaTracker.

题目:什么操作会使得当前线程停止。
A:一个InterruptedException 异常被捕获 大家都知道的嘛 (一般通过interrupt方法 中断线程) 如果抓到一个线程 都会关紧catch里面 然后中断当前操作,A正确。
B:线程执行了wait()方法。 线程使用了wait方法,会强行打断当前操作,(暂停状态,不会中断线程) 进入阻塞(暂停)状态,然后需要notify方法或notifyAll方法才能进入就绪状态。 B 正确。
C:当前线程创建了一个新的线程。 新创建的线程不会抢占时间片,只有等当前线程把时间片用完,其他线程才有资格拿到时间片去执行。
D:一个高优先级别的线程就绪。 如C相同,你优先级别再高 也待等我现在弄完才会给你。(就像我们玩游戏,会员虽然有排队优先权,但是还是要等正在登陆的用户进去游戏之后才能抢到他原来那个位置,不能说我在过关卡的过程中你一脚把我踢开,然后霸占我的位置吧,我原来的那些数据咋办!!!)
E:线程在MediaTracker上执行了waitforID()调用。
这个应该大家也不太熟悉。这个类是awt里面的,我查API才知道。
然后他的功能是加载图像,直到完成之前,该方法一直等待!这个方法是必须要抛出A选项的InterruptedException 异常的 说明这玩意会让其他线程 wait他完成! 所以会暂停当前线程~~大概是这样吧哈哈哈! E选项我没选对! 这还是真的!。!
309 以下说法错误的是(C)

数组是一个对象

数组不是一种原生类

数组的大小可以任意改变

在Java中,数组存储在堆中连续内存空间里

在java中,数组是一个对象, 不是一种原生类,对象所以存放在堆中,又因为数组特性,是连续的,只有C不对
Java中数组是对象,不是基本数据类型(原生类),大小不可变且连续存储,因为是对象所以存在堆中
数组长度在创建时就确定了,要改变数组长度只能重新创建新的数组,将原有数组复制到新的数组之中。这也是ArrayList扩容时候的效率低于LinkedList的原因。

310 Web程序中,当前用户上下文信息应该保存在下面哪个对象中(C)

page

request

session

Application

JSP 四大作用域: page (作用范围最小)、request、session、application(作用范围最大)。

存储在application对象中的属性可以被同一个WEB应用程序中的所有Servlet和JSP页面访问。(属性作用范围最大)
存储在session对象中的属性可以被属于同一个会话(浏览器打开直到关闭称为一次会话,且在此期间会话不失效)的所有Servlet和JSP页面访问。
存储在request对象中的属性可以被属于同一个请求的所有Servlet和JSP页面访问(在有转发的情况下可以跨页面获取属性值),例如使用PageContext.forward和PageContext.include方法连接起来的多个Servlet和JSP页面。
存储在pageContext对象中的属性仅可以被当前JSP页面的当前响应过程中调用的各个组件访问,例如,正在响应当前请求的JSP页面和它调用的各个自定义标签类。

当前用户上下文信息:session
appication:当前应用
pageContext:当前页面
request:当前请求

重点在 当前用户 , application能被同一个应用程序的所有用户访问,所以当前用户的信息就不宜保存在application中
session会话对象,一个会话只可能是一个用户的,生命周期默认30分钟,也可以自行定义,当前会话结束(如关闭浏览器),当前session被销毁。所以当前用户的信息应该保存在session中

311 下列哪个选项是Java调试器?如果编译器返回程序代码的错误,可以用它对程序进行调试。©

java.exe

javadoc.exe

jdb.exe

javaprof.exe

javac.exe是编译.java文件
java,exe是java虚拟机
javadoc.exe用来制作java文档
jdb.exe是java的调试器
javaprof,exe是剖析工具

312 下面哪一项不是加载驱动程序的方法?(A)

通过DriverManager.getConnection方法加载

调用方法 Class.forName

通过添加系统的jdbc.drivers属性

通过registerDriver方法注册

加载驱动方法
1.Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);
2. DriverManager.registerDriver(new com.mysql.jdbc.Driver());
3.System.setProperty(“jdbc.drivers”, “com.mysql.jdbc.Driver”);

313在Java中,关于HashMap类的描述,以下错误的是(A)?

HashMap能够保证其中元素的顺序

HashMap允许将null用作值

HashMap允许将null用作键

HashMap使用键/值得形式保存数据

HashMap的底层是由数组加链表实现的,对于每一个key值,都需要计算哈希值,然后通过哈希值来确定顺序,并不是按照加入顺序来存放的,因此可以认为是无序的,但不管是有序还是无序,它都一个自己的顺序。故A错。
最开始有Hashtable,Hashtable是不允许key和value的值为空的,但后来开发者认为有时候也会有key值为空的情况,因为可以允许null为空,通过查看HashMap的源代码就知道:if(key = null) {putForNullKey(value);};
Map底层都是用key/value键值对的形式存放的

HashMap(集合)中值的存储是无序的,依靠键值来存取元素,一个键对应一个值,就是说通过键来找值,并且键值都可为空

A.HashMap不能保证元素的顺序,而LinkedHashMap可以保持数据的插入顺序,TreeMap可以按照键值进行排序(可自定比较器)
B.HashMap允许存在多条null值
C.HashMap允许且仅允许一条null键
D.Map就是通过键/值形式保存数据的

314 Which lines of the following will produce an error?A

1. byte a1 = 2, a2 = 4, a3;
2. short s = 16;
3. a2 = s;
4. a3 = a1 * a2; 
Line 3 and Line 4

Line 1 only

Line 3 only

Line 4 only

short类型转为byte类型出错
a1*a2结果为int类型,转为byte类型出错

数值型变量在默认情况下为Int型,byte和short型在计算时会自动转换为int型计算,结果也是int 型。所以a1*a2的结果是int 型的。

byte+byte=int,低级向高级是隐式类型转换,高级向低级必须强制类型转换,byte

315 当编译并运行下面程序时会发生什么结果(D)

public class Bground extends Thread{
    public static void main(String argv[]){
        Bground b = new Bground();
        b.run();
    }
    public void start(){
        for(int i=0;i<10;i++){
            System.out.println("Value of i = "+i);
        }
    }
}
编译错误,指明run方法没有定义

运行错误,只鞥呢run方法没有定义

编译通过并输出09

编译通过,但无输出

对于线程而言,start是让线程从new变成runnable。run方法才是执行体的入口。
但是在Thread中,run方法是个空方法,没有具体实现。
Bground继承了Thread,但是没有重写run方法,那么调用run方法肯定是无输出。

这题可以用面向对象的思想即可解决
首先继承Thread,然后调用run方法,bgroud并没有重写run方法,那么就是调用父类Thread的run方法。
然后查看父类代码

@Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

private Runnable target;
其中target是Runnable对象
明显target并没有显示初始化。
所以不会有显示。
一般target的初始化是这样的,将runnable对象作为thread参数进行线程的创建

public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

再看init()

private void init(ThreadGroup g, Runnable target,String name,long stackSize) {
        init(g, target, name, stackSize, null);
    }

在init(g, target, name, stackSize, null),可以找到this.target = target;
此时进行了初始化。

最后说一说,Thread 的执行过程,Theard的启动方法是start().线程类调用start();然后执行start0()本地方法,然后就没办法再追溯下去了。
start我听过别人说,是一个准备工作(比如你要吃苹果,不得先洗一下,真正吃时间是洗完后),并没有获得cpu,调用run()才是获得了cpu

316 运行代码,输出的结果是(A)

public class P {
public static int abc = 123;
static{
System.out.println("P is init");
}
}
public class S extends P {
static{
System.out.println("S is init");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(S.abc);
}
}
P is init<br />123

S is init<br />P is init<br />123

P is init<br />S is init<br />123

S is init<br />123

属于被动引用不会出发子类初始化
1.子类引用父类的静态字段,只会触发子类的加载、父类的初始化,不会导致子类初始化
2.通过数组定义来引用类,不会触发此类的初始化
3.常量在编译阶段会进行常量优化,将常量存入调用类的常量池中, 本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。

不会初始化子类的几种

  1. 调用的是父类的static方法或者字段
    2.调用的是父类的final方法或者字段
  2. 通过数组来引用

子类引用父类的静态字段,只会触发子类的加载、父类的初始化,不会导致子类初始化
而静态代码块在类初始化的时候执行!!

经过代码测试:
当直接new 子类 创建时的执行顺序为:父类静态块、子类静态块、父类构造方法、子类构造方法。
当new创建子类数组时,不加载任何东西
当用父类名调用父类静态变量、方法时:加载父类静态块
当用子类名调用父类静态变量、方法时:加载父类静态块
当用子类名调用子类特有静态变量、方法时:加载父类静态块、加载子类静态块

触发类初始化:

访问类的静态元素(包括静态成员变量,静态方法,构造函数)
子类初始化时会优先为父类初始化 

只要记住,加载跟初始化不是一回事就好了,使用类的时候,不管怎样,这个类必须已经加载到内存当中了,然而初始化没有,就不好说了。被动引用不会触发初始化,也就不会触发static{}代码块。

317 以下代码可以使用的修饰符是:(ABD)

public interface Status {
 /*INSERT CODE HERE*/  int MY_VALUE=10;
 }
final

static

abstract

public

abstract只能修饰类和方法 不能修饰字段
接口中字段的修饰符:public static final(默认不写)
接口中方法的修饰符:public abstract(默认不写)

318以下哪些内存区域属于JVM规范?(  ADE)

方法区

实例变量

静态变量

程序计数器

虚拟机栈

JVM内存区:程序计数器、虚拟机栈、本地方法栈、堆、方法区(包括常量池)。
不属于JVM内存区:直接内存(Direct Memory),用户I/O操作

牛客刷题笔记--(java基础301-400)_第1张图片319关于volatile关键字,下列描述不正确的是?BD

volatile修饰的变量,每次更新对其他线程都是立即可见的。

对volatile变量的操作是原子性的。

对volatile变量的操作不会造成阻塞。

不依赖其他锁机制,多线程环境下的计数器可用volatile实现。

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

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

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

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

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

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

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

所谓 volatile的措施,就是

  1. 每次从内存中取值,不从缓存中什么的拿值。这就保证了用 volatile修饰的共享变量,每次的更新对于其他线程都是可见的。
  2. volatile保证了其他线程的立即可见性,就没有保证原子性。
    3.由于有些时候对 volatile的操作,不会被保存,说明不会造成阻塞。不可用与多线程环境下的计数器。

320 Java Application(Java 应用程序)源程序文件编译后的字节码文件的扩展名是( B )。

java

class

exe

jar

A: .java是java程序的源代码文件 B: .class不是类的扩展名,JVM并不能直接运行java源文件,需要通过javac将java源文件编译成字节码文件,也就是.class文件,JVM在运行某个类的时候,通过加载指定该.class文件就可以,因为class文件名与类名相同,但是他俩并不是一回事,运行的是类,不是文件。 C: java可以编写成.exe,虽然是exe文件,但是不代表是windows可执行文件,尽管扩展名一样 D: 可以打包成jar,需要有jdk支持,通过JVM运行,这个才是java真正的运行包。

java文件的源码的后缀是.java

1, Java文件经过JVM编译成字节码文件,即.class文件,将字节码文件在不同的操作系统中运行时,操作系统再将字节码文件编译成机器码文件。这就是Java跨平台
2, JAR 文件就是 Java Archive File,顾名思意,它的应用是与 Java 息息相关的,是 Java 的一种文档格式。JAR 文件非常类似 ZIP 文件——准确的说,它就是 ZIP 文件,所以叫它文件包。JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中,包含了一个 META-INF/MANIFEST.MF 文件,这个文件是在生成 JAR 文件的时候自动创建的

321 请问以下代码运行结果是:D
牛客刷题笔记--(java基础301-400)_第2张图片

try catch

try finally  catch

try finally

try catch finally

throws:写在方法声明之后,表示方法可能抛出异常,调用者需要处理这个异常。
throw:写在方法体中,表示方法一定会抛出一个异常,要么try…catch处理,要么throws抛出。

结果为try catch finally,运行过程如下: 在执行到try代码块中,首先输出try,然后抛出异常,直接跳转到catch中,输出catch,然后跳转到finally块中,输出finally。

322 从运行层面上来看,从四个选项选出不同的一个。B

JAVA

Python

objectC

C#

A,C,D都是类C语言,B不是 Python是解释执行的,其他语言都需要先编译

Python 只有它是动态语言
动态语言的定义:动态编程语言 是 高级程序设计语言 的一个类别,在计算机科学领域已被广泛应用。它是一类 在 运行时可以改变其结构的语言 :例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。动态语言目前非常具有活力。众所周知的 ECMAScript ( JavaScript )便是一个动态语言,除此之外如 PHP 、 Ruby 、 Python 等也都属于动态语言,而 C 、 C++ 等语言则不属于动态语言。

牛客刷题笔记--(java基础301-400)_第3张图片
强类型strongly typed: 如果一种语言的所有程序都是well behaved——即不可能出现forbidden behaviors,则该语言为strongly typed。
弱类型weakly typed: 否则为weakly typed。比如C语言的缓冲区溢出,属于trapped errors,即属于forbidden behaviors…故C是弱类型

前面的人也说了,弱类型语言,类型检查更不严格,如偏向于容忍隐式类型转换。譬如说C语言的int可以变成double。 这样的结果是:容易产生forbidden behaviours,所以是弱类型的
动态、静态类型

静态类型 statically: 如果在编译时拒绝ill behaved程序,则是statically typed;
动态类型dynamiclly: 如果在运行时拒绝ill behaviors, 则是dynamiclly type

323以下JAVA程序代码的输出是C

public static void main(String args[]) {
    System.out.println(17^5);
}
12

22

20

1419857

位异运算符号。
运算规则是:两个数转为二进制,然后从高位开始比较,如果相同则为0,不相同则为1。
17:0001 0001
5: 0000 0101
结果:0001 0100 转10进制:20

&按位与 |按位或 ~取反 ^异或

324 下面叙述那个是正确的?(B)

java中的集合类(如Vector)可以用来存储任何类型的对象,且大小可以自动调整。但需要事先知道所存储对象的类型,才能正常使用。

在java中,我们可以用违例(Exception)来抛出一些并非错误的消息,但这样比直接从函数返回一个结果要更大的系统开销。

java接口包含函数声明和变量声明。

java中,子类不可以访问父类的私有成员和受保护的成员。

B选项说的情况就是我们自定义异常的情况,请仔细读:我们可以用违例(Exception)来抛出一些并非错误的消息,可以,并非错误的消息。比如我自定义一个异常,若一个变量大于10就抛出一个异常,这样就对应了B选项说的情况,我用抛出异常说明这个变量大于10,而不是用一个函数体(函数体内判断是否大于10,然后返回true或false)判断,因为函数调用是入栈出栈,栈是在寄存器之下的速度最快,且占的空间少,而自定义异常是存在堆中,肯定异常的内存开销大!所以B对。
C选项说的是接口包含方法声明和变量声明。因为接口中方法默认是 abstract public,所以在接口只写函数声明是符合语法规则。但是变量默认是用public final static 修饰的,意思它是静态常量,常量不管在接口中还是类中必须在声明时初始化!所以C的后半句是错的,必须在声明时并给出初始化!

接口中只有常量定义,没有变量声明。

A.vector是线程安全的ArrayList,在内存中占用连续的空间。初始时有一个初始大小,当数据条数大于这个初始大小后会重写分配一个更大的连续空间。如果Vector定义为保存Object则可以存放任意类型。

B.try{}catch{}会增加额外的开销

C.接口中声明的’变量’必须为public final static,所以为常量

D.子类可以访问父类受保护的成员
325下面哪些语法结构是正确的?AC

public class A extends B implements C

public class A implements A B

public class A implements B,C,D

public implements B

A选项- 标准写法,正确

public class A extends B implements C

B选项- implements接的是接口类 而A此处的定义又是class
循环矛盾,必然错误

public class A implements A B

C选项- 正确,一个类可以实现多个接口

public class A implements B,C,D

D选项- 错误。

public implements B

另外补充一点,如果一个类既继承了某个基类,又实现了接口。那么extends关键字必须在implements之前。

继承只能有一个,接口可以有多个

326 下面代码将输出什么内容:(B)

public class SystemUtil{
    public static boolean isAdmin(String userId){
        return userId.toLowerCase()=="admin";
    }
    public static void main(String[] args){
        System.out.println(isAdmin("Admin"));
    }
}
true

false

1

编译错误

equals和==的区别 ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。

在源码中 toLowerCase 是重新 new String()

所以为 == 是比较对象是否是同一个对象,所以为 false 。

首先要知道toLowerCase()的底层实现是
return new String(result, 0, len + resultOffset);
所以底层new 了一个新的字符串并且返回。
牛客刷题笔记--(java基础301-400)_第4张图片 因为0x0003 不等于0x0002 ,所以返回false,如果是equals 则返回true
因为== 比较的是地址。
equals 比较的话 先比较地址,如果相等,直接返回true
然后看比较的对象是不是String类型,如果不是直接返回false
如果是的话,则依次比较每个字符,如果全部相等,则返回true

327 What will happen when you attempt to compile and run the following code?D

public class Test{
static{
   int x=5;
}
static int x,y;
public static void main(String args[]){
   x--;
   myMethod( );
   System.out.println(x+y+ ++x);
}
public static void myMethod( ){
  y=x++ + ++x;
 }
}
compiletime error

prints:1

prints:2

prints:3

prints:7

prints:8

1.静态语句块中x为局部变量,不影响静态变量x的值
2.x和y为静态变量,默认初始值为0,属于当前类,其值得改变会影响整个类运行。
3.java中自增操作非原子性的
main方法中:

执行x--后 x=-1
调用myMethod方法,x执行x++结果为-1(后++),但x=0,++x结果1,x=1 ,则y=0
x+y+ ++x,先执行x+y,结果为1,执行++x结果为2,得到最终结果为3 

328 抽象类方法的访问权限默认都是public。( × )

关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default

关于接口
JDK 1.8以前,接口中的方法必须是public的
JDK 1.8时,接口中的方法可以是public的,也可以是default的
JDK 1.9时,接口中的方法可以是private的

329 关于JSP生命周期的叙述,下列哪些为真?AC

JSP会先解释成Servlet源文件,然后编译成Servlet类文件

每当用户端运行JSP时,jsp init()方法都会运行一次

每当用户端运行JSP时,jsp service()方法都会运行一次

每当用户端运行JSP时,jsp destroy()方法都会运行一次

Jsp只会在客户端第一次发请求的时候被编译,之后的请求不会再编译,同时tomcat能自动检测jsp变更与否,变更则再进行编译。

第一次编译并初始化时调用: init() ;销毁调用: destroy() 。在整个jsp生命周期中均只调用一次。

service()方法是接收请求,返回响应的方法。每次请求都执行一次,该方法被HttpServlet封装为doGet和doPost方法

牛客刷题笔记--(java基础301-400)_第5张图片

servlet生命周期:init 、service、destory
除了init只初始化一次外、其他 用户端运行JSP时方法都会运行一次

330下面程序的输出是:(D)

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

fmnwxy

wxyfmn

Fmnwxy

String x=“fmn”; “fmn”是在常量池里的不可变对象。
x.toUpperCase(); 在堆中new一个"FMN"对象,但无任何引用指向它
String y=x.replace(‘f’,‘F’); 在堆中 new一个"Fmn"对象,y指向它。
y=y+“wxy”; 在堆中 重新new一个"Fmnwxy"对象, 修改y指向,现在y指向它

本题主要考察String对象的不可变性。
toUpperCase()会对当前对象进行检查 如果不需要转换直接返回当前对象,否则new一个新对象返回;
replace()如果两个参数相同,则直接返回,否则new一个新对象,所以这里y指向"Fmn";
y=y+“wxy” 这里修改y所指向的字符串对象,让它由指向"Fmn"变成指向"Fmnxyz".

331 枚举(enum)属于原始数据类型(primitive type)(X)

在Java中,变量有两种类型,一种是原始类型,一种是引用类型。

原始类型一共有8种,它们分别是char,boolean,byte,short,int,long,float,double。在Java API中,有它们对应的包装类,分别是(首字母大写)Character,Boolean,Byte,Short,Integer,Long,Float,Double(char,int的变化稍微大点)。

JAVA JVM对于不同的原始类型会分配不同的存储空间,具体分配如下:

byte : 1个字节 8位
最大值: 127 (有符号)

short : 2个字节 16位 32767

int : 4个字节 32位 2147483647

long: 8个字节 64位 9223372036854775807

float: 4个字节 32位 3.4028235E38
double:8个字节 64位 1.7976931348623157E308

枚举(enum)类型是Java 5新增的特性,它是一种新的类型,允许用常量来表示特定的数据片断,而且全部都以类型安全的形式来表示,是特殊的类,可以拥有成员变量和方法

枚举类是一种特殊的类,既然是类。那他就不是原始数据类型了

Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
byte,short,int,long,float,double,boolean,char.

332 关于ASCII码和ANSI码,以下说法不正确的是(D)?

标准ASCII只使用7个bit

在简体中文的Windows系统中,ANSI就是GB2312

ASCII码是ANSI码的子集

ASCII码都是可打印字符

A、标准ASCII只使用7个bit,扩展的ASCII使用8个bit。
B、ANSI通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码。不同 ANSI 编码之间互不兼容。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
C、ANSI通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符,即ASCII码
D、ASCII码包含一些特殊空字符

333有如下一段代码,请选择其运行结果(C)

public class StringDemo{
  private static final String MESSAGE="taobao";
  public static void main(String [] args) {
    String a ="tao"+"bao";
    String b="tao";
    String c="bao";
    System.out.println(a==MESSAGE);
    System.out.println((b+c)==MESSAGE);
  }
}  
true true

false false

true false

false true
要注意两个问题:
1,字符串在java中存储在字符串常量区中
2==判断的是对象引用是否是同一个引用,判断字符串相等要用equals方法
首先判断a==MESSAGE 同一份字符串常量在内存中只有一份,因此是同一地址,返回true
再次比较(b+c)==MESSAGE 这相当于 new String(b+c)==MESSAGE 这里new了一个String对象,所以返回false 

334 以下哪几个是java中的集合类型?ABD

Vector

Set

String

List

牛客刷题笔记--(java基础301-400)_第6张图片335 假定Base b = new Derived(); 调用执行b.methodOne()后,输出结果是什么? A

public class Base
{
   public void methodOne()
   {
      System.out.print("A");
      methodTwo();
   }

   public void methodTwo()
   {
      System.out.print("B");
   }
}

public class Derived extends Base
{
   public void methodOne()
   {
      super.methodOne();
      System.out.print("C");
   }

   public void methodTwo()
   {
      super.methodTwo();
      System.out.print("D");
   }
}
ABDC

AB

ABCD

ABC

只要是被子类重写的方法,不被super调用都是调用子类方法

关于子类继承父类中方法的调用,只要不是用super调用,调用的都是子类中覆写父类的方法。
如果将这道题目修改一下,将父类中的methodTwo()改成静态方法,代码如下:
结果为:ABC
牛客刷题笔记--(java基础301-400)_第7张图片

这是一道类多态的向上转型题。
Base b = new Derived();
向上转型:父类只能调用父类方法或者子类覆写后的方法,而子类中的单独方法则是无法调用的。
因此:
调用的顺序是:(1)、(2)、(3)、(4)、(5)、(6)、(7) ; 得到的结果是:ABDC

class Base
{ public void methodOne()  // (3)
    {
        System.out.print("A");
        methodTwo();  //执行到这里的时候调用子类的覆盖方法 (4)
    } public void methodTwo() // (7)
    {
        System.out.print("B");
    }
} 

 class Derived extends Base { public void methodOne() // (1)
    { super.methodOne();   // (2)
        System.out.print("C");
    } public void methodTwo()  //该方法为重写了父类的方法 (5)
    { super.methodTwo(); //(6)
        System.out.print("D");
    }
}

继承关系中,用多态创建子类对象,我们在调用一个父类被子类重写的方法时,不管是在子类中调用还是在父类中调用,不被super调用都是调用子类方法,只有用super调用时才是调用父类的方法。

336 StringBuffer类对象创建之后可以再修改和变动.(√)
String,StringBuffer,StringBuilder,都实现了CharSequence接口。
String是个不可继承类(final修饰),也是个不可变类(内部char数组被final修饰)。
StringBuffer和StringBuilder内部都是一般的动态数组,所以可变。前者是线程安全的,因为方法基本都被synchronized修饰了。

stringbuffer是可变长度的,可通过append,insert,remove等方法改变其长度

1.String对象不可变、StringBuffer对象可变的含义: 举个例子:String str = “aa”; str = “aa”+“bb”; 此时str的值为"aabb",但是"aabb"不是在开始的字符串"aa"后面直接连接的"bb",而是又新生成了字符串"aabb",字符串"aa"一旦被初始化,那么它的值不可能再改变了。 StringBuffer strb = StringBuffer(“aa”); strb.append(“bb”); 此时的strb的值也为"aabb",但是"aabb"是直接在开始的字符串"aa"后面连接的“bb”,并没有生成新的字符串。

337执行如下程序,输出结果是( C)

class Test
{
     private int data;
     int result = 0;
     public void m()
     {
         result += 2;
         data += 2;
         System.out.print(result + "  " + data);
     }
 }
 class ThreadExample extends Thread
 {
     private Test mv;
     public ThreadExample(Test mv)
     {
         this.mv = mv;
     }
     public void run()
     {
         synchronized(mv)
         {
             mv.m();
         }
     }
 }
 class ThreadTest
 {
     public static void main(String args[])
     {
         Test mv = new Test();
         Thread t1 = new ThreadExample(mv);
         Thread t2 = new ThreadExample(mv);
         Thread t3 = new ThreadExample(mv);
         t1.start();
         t2.start();
         t3.start();
     }
 }
0 22 44 6

2 42 42 4

2 24 46 6

4 44 46 6

Test mv =newTest()声明并初始化对data赋默认值
使用synchronized关键字加同步锁线程依次操作m()
t1.start();使得result=2,data=2,输出即为2 2
t2.start();使得result=4,data=4,输出即为4 4
t3.start();使得result=6,data=6,输出即为6 6
System.out.print(result +" "+ data);是print()方法不会换行,输出结果为2 24 46 6
加了锁,所以三条线程依次计算就好了,嗯,很和谐
只是new出线程对象,所以调用的方法是同一个对象中的方法,三个线程所访问的数据data和result都是同一个堆上的内容。

338 有关finally语句块说法正确的是(ABC )

不管catch是否捕获异常,finally语句块都是要被执行的

在try语句块或catch语句块中执行到System.exit(0)直接退出程序

finally块中的return语句会覆盖try块中的return返回

finally 语句块在 catch语句块中的return语句之前执行

如果try语句里有return,那么代码的行为如下:
1.如果有返回值,就把返回值保存到局部变量中
2.执行jsr指令跳到finally语句里执行
3.执行完finally语句后,返回之前保存在局部变量表里的值

如果try,finally语句里均有return,忽略try的return,而使用finally的return.

D.不是return之前,是return执行完成之前,return表达式的结果会暂时保存起来,不会被改变

1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

举例:

情况1:try{} catch(){}finally{} return;
显然程序按顺序执行。

情况2:try{ return; }catch(){} finally{} return;
程序执行try块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,最后执行try中return;
finally块之后的语句return,因为程序在try中已经return所以不再执行。

情况3:try{ } catch(){return;} finally{} return;
程序先执行try,如果遇到异常执行catch块,
有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,
最后执行catch块中return. finally之后也就是4处的代码不再执行。
无异常:执行完try再finally再return.

情况4:try{ return; }catch(){} finally{return;}
程序执行try块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,因为finally块中有return所以提前退出。

情况5:try{} catch(){return;}finally{return;}
程序执行catch块中return之前(包括return语句中的表达式运算)代码;
再执行finally块,因为finally块中有return所以提前退出。

情况6:try{ return;}catch(){return;} finally{return;}
程序执行try块中return之前(包括return语句中的表达式运算)代码;
有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
则再执行finally块,因为finally块中有return所以提前退出。
无异常:则再执行finally块,因为finally块中有return所以提前退出。

最终结论:任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话。
如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,
编译器把finally中的return实现为一个warning。

339 下面关于变量及其范围的陈述哪些是不正确的(BC)

实例变量是类的成员变量

实例变量用关键字static声明

在方法中定义的局部变量在该方法被执行时创建

局部变量在使用前必须被初始化

A.类的成员变量包括实例变量和类变量(静态变量),成员方法包括实例方法和类方法(静态方法)。 A正确
B.类变量(静态变量)用关键字static声明,B错误
C.方法中的局部变量在方法被调用加载时开始入栈时创建,方法入栈创建栈帧包括局部变量表操作数栈,局部变量表存放局部变量,并非在执行该方法时被创建,C错误
D.局部变量被使用前必须初始化,否则程序报错。D正确

c选项应该是在线程为该方法创建栈桢时被创建,而不是方法执行时创建

不是局部变量在该方法被执行/调用时创建,而是应该为在该变量被声明并赋值时创建,可以理解为“当代码执行到该变量被赋值的代码时才被创建”
栈会为每个方法在运行的时候分配一块独立的栈帧内存区域,栈帧又包含“局部变量表”、“操作数栈”、“动态链接”以及“方法出口”四个部分

340 关键字super的作用是? D

用来访问父类被隐藏的非私有成员变量

用来调用父类中被重写的方法

用来调用父类的构造函数

以上都是

正确答案D:
1:特殊变量super,提供了对父类的访问。
2:可以使用super访问父类被子类隐藏的变量或覆盖的方法。
3:每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
4:构造是不能被继承的。

341以下叙述正确的是 D

实例方法可直接调用超类的实例方法

实例方法可直接调用超类的类方法、

实例方法可直接调用子类的实例方法

实例方法可直接调用本类的实例方法

首先,实例成员包括实例变量和实例方法,也就是我们平时说的成员变量和成员方法。其次,静态变量也叫做类变量,静态方法也叫类方法,静态变量和静态方法统称静态成员也叫作类成员。类成员是可以用类名.类变量或类方法的。最后,这道题就是考你父类子类之间变量区分。答案是D

A错误,类的实例方法是与该类的实例对象相关联的,不能直接调用,只能通过创建超类的一个实例对象,再进行调用
B错误,当父类的类方法定义为private时,对子类是不可见的,所以子类无法调用
C错误,子类具体的实例方法对父类是不可见的,所以无法直接调用, 只能通过创建子类的一个实例对象,再进行调用
D正确,实例方法可以调用自己类中的实例方法

在java中我们称超类为父类。这题涉及父子类关系,如果父类里被private修饰,则子类是无法继承和访问的,而父类访问子类,需要new一个对象才能访问,不能直接访问。本题中只有d选项是正确的,一个类访问本类是绝对可行的。

342 执行下面的程序段,语句3的执行次数为(C)

for   (i=0; i<=n-1; i++)   (1)
for  (j=n; j>i; j--(2)
state;                      (3)
n(n+2)/2

(n-1)(n+2)/2

n(n+1)/2

(n-1)(n+2)

选c,外循环有n次,当i=0,内循环为n次,当i=1,内循环为n-1次,当i=2时,内循环为n-2次,以此类推,总次数为n+(n-1)+(n-2)+…+2+1,就是个等差数列,等于n(n+1)/2。

343指出下列程序运行的结果(B)

public class Example{
    String str = new String("good");
    char[ ] ch = { 'a' , 'b' , 'c' };
    public static void main(String args[]){
        Example ex = new Example();
        ex.change(ex.str,ex.ch);
        System.out.print(ex.str + " and ");
        System.out.print(ex.ch);
    }
    public void change(String str,char ch[ ]){
        str = "test ok";
        ch[0] = 'g';
    }
}
good and  abc

good and gbc

test ok and abc

test ok and gbc
 简单总结一下:直接赋值而不是使用new关键字给字符串初始化,在编译时就将String对象放进字符串常量池中;使用new关键字初始化字符串时,是在堆栈区存放变量名和内容;字符串的拼接操作在程序运行时,才在堆中创建对象。一般,可以认为使用"=="比较的是引用,equals比较的是内容。对于上面的题,看完下面的几个例子,你就会有所感悟:String str = new String("good");是在编译时在堆栈中创建对象和分配内容,而在传参的时候,传递的是地址,把外面的str引用地址复制了一份给方法内的str而不是里面的内容。
看例子:;
例子A:
String str1 = "java";
String str2 = "java";
System.out.print(str1==str2);
大部分人也许认为会输出false,因为==比较的是引用,equals比较的是内容。可以在自己的机子上运行一 下,结果是true!原因很简单,String对象被放进常量池里了,再次出现“java”字符串的时候,JVM很兴奋地把str2的引用也指向了 “java”对象,它认为自己节省了内存开销。不难理解吧 呵呵
例子B:
String str1 = new String("java");
String str2 = new String("java");
System.out.print(str1==str2);
看过上例的都学聪明了,这次肯定会输出true!很不幸,JVM并没有这么做,结果是false。原因很简单,例子A中那种直接赋值(而没有通过new关键字实例化的字符串变量)声明的方式确实是在 String常量池创建“java”对象,但是一旦看到new关键字,JVM会在堆中为String分配空间。两者声明方式貌合神离,这也是我把“如何创 建字符串对象”放到后面来讲的原因。大家要沉住气,还有一个例子。
例子C:
String str1 = "java";            //直接赋值而不是使用new关键字给字符串初始化,在编译时就将String对象放进字符串常量池中
String str2 = "blog"; //直接赋值而不是使用new关键字给字符串初始化,在编译时就将String对象放进字符串常量池中
String s = str1+str2;            //字符串的拼接操作在程序运行时,才在堆中创建对象,
System.out.print(s=="javablog");
再看这个例子,很多同志不敢妄言是true还是false了吧。爱玩脑筋急转弯的人会说是false吧……恭喜你,你会抢答了!把那个“吧”字去掉你就完 全正确。原因很简单,JVM确实会对型如String str1 = "java"; 的String对象放在字符串常量池里,但是它是在编译时刻那么做的,而String s = str1+str2; 是在运行时刻才能知道(我们当然一眼就看穿了,可是Java必须在运行时才知道的,人脑和电脑的结构不同),也就是说str1+str2是在堆里创建的, s引用当然不可能指向字符串常量池里的对象。没崩溃的人继续看例子D。
例子D:
String s1 = "java";
String s2 = new String("java");
System.out.print(s1.intern()==s2.intern());
intern()是什么东东?反正结果是true。如果没用过这个方法,而且训练有素的程序员会去看JDK文档了。简单点说就是用intern()方法就可以用“==”比较字符串的内容了。在我看到intern()方法到底有什么用之前,我认为它太多余了。其实我写的这一条也很多余,intern()方法 还存在诸多的问题,如效率、实现上的不统一……
例子E:
String str1 = "java";
String str2 = new String("java");
System.out.print(str1.equals(str2));
无论在常量池还是堆中的对象,用equals()方法比较的就是内容,就这么简单! 

牛客刷题笔记--(java基础301-400)_第8张图片 首先说下String确实是个不可变对象,这个不可变是JDK特有的,写JAVA的人特意针对的
但是这与本题无关,题目中的形参str只是原引用ex.str的一个引用副本,传的是一个副本地址值,这个值与ex.str地址值是不一样的,但是它们同时指向了堆中的对象new String(“good”),当你在函数中改变形参也就是地址的副本值也就是这句str=“test ok"只是将副本地址指向常量"test ok”,并没有改变原ex.str的指向方向,它还是指向对象new String(“good”)的
char数组与String一样传的也是地址的副本,但是关键是形参ch它没有新的指向 ch[0]只是ch在指向原对象时改变了对象的内部结构, 所以在ex.ch指向与它是同一个对象的情况下当然也会随之变化

344 下面有关servlet service描述错误的是?B

不管是post还是get方法提交过来的连接,都会在service中处理

doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的

service()是在javax.servlet.Servlet接口中定义的

service判断请求类型,决定是调用doGet还是doPost方法

doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的
doget/dopost与Http协议有关,是在 javax.servlet.http.HttpServlet 中实现的
牛客刷题笔记--(java基础301-400)_第9张图片
注意以下几点:
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.Servle接口,且javax.servlet.http.HttpServlet 是 javax.servlet.GenericServlet 的子类。只有最先定义好了的service方法才可以处理所有的请求。

345 下面哪些Java中的流对象是字节流?ABCD

FileInputStream

BufferedInputStream

PushbackInputStream

ByteArrayInputStream

stream结尾都是字节流,reader和writer结尾都是字符流 两者的区别就是读写的时候一个是按字节读写,一个是按字符。 实际使用通常差不多。 在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。 只是读写文件,和文件内容无关的,一般选择字节流。

牛客刷题笔记--(java基础301-400)_第10张图片

牛客刷题笔记--(java基础301-400)_第11张图片
Java主要分为字节流和字符流如下:

字节流:
InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
字符流
Reader
|-- InputStreamReader (byte->char 桥梁)
|-- BufferedReader (常用)
Writer
|-- OutputStreamWriter (char->byte 桥梁)
|-- BufferedWriter
|-- PrintWriter (常用)

346 关于equals和hashCode描述正确的是 (ABC)

两个obj,如果equals()相等,hashCode()一定相等(符合代码规范的情况下)

两个obj,如果hashCode()相等,equals()不一定相等

两个不同的obj, hashCode()可能相等

其他都不对
==”:作用是判断两个对象的地址是否相等,即,判断两个对象是不是同一个对象,如果是基本数据类型,则比较的是值是否相等。
"equal":作用是判断两个对象是否相等,但一般有两种使用情况
              1.类没有覆盖equals()方法,则相当于通过“==”比较
              2.类覆盖equals()方法,一般,我们都通过equals()方法来比较两个对象的内容是否相等,相等则返回true,如String

地址比较是通过计算对象的哈希值来比较的,hashcode属于Object的本地方法,对象相等(地址相等),hashcode相等,对象不相等,hashcode()可能相等,哈希冲突 

两个对象的equals比较为true,那么他们的HashCode一定相同,反之,两个对象的HashCode相同不一满足equals比较为true,解释一下为什么,这是因为HashCode采用的其实是一种杂凑算法,当然,这业务Java认为最有效的算法,既然是凑出来的那么就有一种情况就是两个不同的对象返回相同的hashCode,并且这种算法越糟糕返回相同的概率越大

hashCode()的存在是为了查找的快捷性,用于在散列存储结构中确定对象的存储地址
如果两个对象 equals相等,则 hashCode()也一定相等
如果 equals方法被重写,则 hashCode()也应该被重写
如果两个对象的 hashCode()相等, equals()方法不一定相等
equals方法没有重写,比较的就是应用类型的变量所指向的对象的地址

347 关于java中的数组,下面的一些描述,哪些描述是准确的:(ACF)

数组是一个对象,不同类型的数组具有不同的类

数组长度是可以动态调整的

数组是一个连续的存储结构

一个固定长度的数组可类似这样定义:int array[100]

两个数组用Object 里equals方法比较时,会逐个遍历其中的元素,对每个元素进行比较

java中不存在 int *a这样的东西做数组的形参

数组用equals比较时,不是比较内容,而是比较的是值(地址,显然是两个对象,地址不同),默认采用的object中的equals来进行比较,看源码的都知道

牛客刷题笔记--(java基础301-400)_第12张图片
equals源码
牛客刷题笔记--(java基础301-400)_第13张图片数组a.equals(数组b),和Arrays.equals(数组a,数组b)是不同的

348 在异常处理中,若try中的代码可能产生多种异常则可以对应多个catch语句,若catch中的参数类型有父类子类关系,此时应该将父类放在后面,子类放在前面。(√)

简单记忆:老将(牛X的)都是最后出马
( 若 catch 中的参数类型有父类子类关系,此时应该将父类放在后面,子类放在前面 )

349Java 的屏幕坐标是以像素为单位,容器的左下角被确定为坐标的起点。(×)

容器的左上角被确定为坐标的起点。

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

生成器

桥接模式

抽象工厂

单例模式

桥接模式:
定义 :将抽象部分与它的实现部分分离,使它们都可以独立地变化。
意图 :将抽象与实现解耦。
桥接模式所涉及的角色

  1. Abstraction :定义抽象接口,拥有一个Implementor类型的对象引用
  2. RefinedAbstraction :扩展Abstraction中的接口定义
  3. Implementor :是具体实现的接口,Implementor和RefinedAbstraction接口并不一定完全一致,实际上这两个接口可以完全不一样Implementor提供具体操作方法,而Abstraction提供更高层次的调用
  4. ConcreteImplementor :实现Implementor接口,给出具体实现
    Jdk中的桥接模式:JDBC
    JDBC连接 数据库 的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不动,原因就是JDBC提供了统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了

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

桥接模式是结构型模式,关注点在依赖关系的维护。对于jdbc技术来说,它解耦了业务与数据库通信协议这两个纬度之间的关系,所以这两个纬度之间的关系就需要一个桥,即Driver,至于DriverManager把这个关系接到哪里就是运行时的事情了。
微观上,从connection的创建来看,它更像一个抽象工厂模式,特定的Driver创建对应的connection。
宏观上,从业务代码与connection的关系来看,关键点在于一个sql怎么转化为对应的通信协议,就属于桥接。

351 以下声明合法的是B

default  String  s

public  final  static  native  int  w( )

abstract  double  d

abstract  final  double  hyperbolicCosine( )

A:java的访问权限有public、protected、private和default的,default不能修饰变量
C:普通变量不能用abstract修饰,abstract一般修饰方法和类
D:被定义为abstract的类需要被子类继承,但是被修饰为final的类是不能被继承和改写的

A:变量不能被defalut修饰

B:native修饰方法,native修饰的方法简单来说就是:一个Java方法调用了一个非Java代码的接口。
定义navtive方法时,并不提供实现体,因为其实现体是用非Java语言在外面实现的。native可以和任何修饰符连用,abstract除外。因为native暗示这个方法时有实现体的,而abstract却显式指明了这个方法没有实现体。

C:abstract修饰方法和类

D:final修饰的方法不能被重写。而abstract定义的方法没有实现,必须被子类重写,明显不能一起使用。

b中的问题涉及到JNI:
native是方法修饰符。Native方法是由另外一种语言(如c/c++,FORTRAN,汇编)实现的本地方法。因为在外部实现了方法,所以在java代码中,就不需要声明了,有点类似于接口方法。Native可以和其他一些修饰符连用,但是abstract方法和Interface方法不能用native来修饰

352 jvm中垃圾回收分为scanvenge gc和full GC,其中full GC触发的条件可能有哪些 CDE

栈空间满

年轻代空间满

老年代满

持久代满

System.gc()

1,新生代:(1)所有对象创建在新生代的Eden区,当Eden区满后触发新生代的Minor GC,将Eden区和非空闲Survivor区存活的对象复制到另外一个空闲的Survivor区中。(2)保证一个Survivor区是空的,新生代Minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。
2,老年代:当Survivor区也满了之后就通过Minor GC将对象复制到老年代。老年代也满了的话,就将触发Full GC,针对整个堆(包括新生代、老年代、持久代)进行垃圾回收。
3,持久代:持久代如果满了,将触发Full GC。

353 以下哪几种方式可用来实现线程间通知和唤醒:AC

Object.wait/notify/notifyAll

ReentrantLock.wait/notify/notifyAll

Condition.await/signal/signalAll

Thread.wait/notify/notifyAll

wait()、notify()和notifyAll()是 Object类 中的方法 ;
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、 notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。

354 下列关于Java语言中String和char的说法,正确的是(C)

String是Java定义的一种基本数据类型。

String是以“\0”结尾的char类型的数组char[]。

使用equals()方法比较两个String是否内容一样(即字符串中的各个字符都一样)。

Char类型在Java语言里面存储的是ASCII码。

A 基本数据类型包括byte,short,int,long,float,double,char,boolean,所以A错。
B,C语言当中是这样,java不是, String内部是用char[]数组实现的,不过结尾不用\0。
C 对,字符串内容比较用equals方法。
D char存储的unicode码,不仅可以存储ascII码,汉字也可以。

Java中的char是Unicode编码。
Unicode编码占两个字节,就是16位,足够存储一个汉字
基本数据类型 byte,short,int,long char float,double boolean String是类 2.String底层是用char[] 数组实现的,但不以"\0"结尾 3.equals()方法比较内容是否相等 4.byte类型储存的是ASCll码

355 Java中基本的编程单元为:A

类

函数

变量

数据

java的基本编程单元是类,基本存储单元是变量。
没有类就没有函数
Java的基本编程单位是类,基本存储单元是变量

356如果一个list初始化为{5,3,1},执行以下代码后,其结果为(B)?

nums.add(6);
nums.add(0,4);
nums.remove(1);
[5, 3, 1, 6]

[4, 3, 1, 6]

[4, 3, 6]

[5, 3, 6]

初始化为{5,3,1}
nums.add(6)后list为{5,3,1,6}
nums.add(0,4)是在0号索引上添加数字4得到list为{4,5,3,1,6}
nums.remove(1)是将1号索引上的5进行remove得到list为{4,3,1,6}索引从0开始的,,,

357 DBMS 中实现事务持久性的子系统是(D)

安全性管理子系统

完整性管理子系统

并发控制子系统

恢复管理子系统

原子性:事务是一组不可分割的操作单元,这组单元要么同时成功要么同时失败(由DBMS的事务管理子系统来实现);
一致性:事务前后的数据完整性要保持一致(由DBMS的完整性子系统执行测试任务);
隔离性:多个用户的事务之间不要相互影响,要相互隔离(由DBMS的并发控制子系统实现);
持久性:一个事务一旦提交,那么它对数据库产生的影响就是永久的不可逆的,如果后面再回滚或者出异常,都不会影响已提交的事务(由DBMS的恢复管理子系统实现的)

要想事物具有持久性,就得在事物出错时及时恢复。

原子性-事务管理子系统。一致性-完整子系统。隔离性-并发控制子系统。持久性-恢复管理子系统

原事~一完~隔并~持恢

358 下面有关Java的说法正确的是( ACDF )

一个类可以实现多个接口

抽象类必须有抽象方法

protected成员在子类可见性可以修改

通过super可以调用父类构造函数

final的成员方法实现中只能读取类的成员变量

String是不可修改的,且java运行环境中对string对象有一个对象池保存

解释一下c选项,意思是父类中的protected方法子类在重写的时候访问权限可以修改,其实就是重写的要素之一,换了个说法而已
final 的成员方法除了能读取类的成员变量,还能读取类变量
牛客刷题笔记--(java基础301-400)_第14张图片359 可以把任何一种数据类型的变量赋给Object类型的变量。(√)
对象类型的不必多说可以赋值;而八大基础数据类型会自动装箱后赋值给Object,所以编译运行都不会报错
Java中一切都是对象,Object是所有类的根类!

360要使某个类能被同一个包中的其他类访问,但不能被这个包以外的类访问,可以( A)

让该类不使用任何关键字

使用private关键字

使用protected关键字

使用void关键字

default和protected的区别是:
前者只要是外部包,就不允许访问。
后者只要是子类就允许访问,即使子类位于外部包。

总结:default拒绝一切包外访问;protected接受包外的子类访问
牛客刷题笔记--(java基础301-400)_第15张图片

包以外的类包括子类
外部包 > 子类 > 本包 > 该类内部
publi c> protected > default > private

361对于子类的构造函数说明,下列叙述中错误的是( A )。

子类可以继承父类的构造函数。

子类中调用父类构造函数不可以直接书写父类构造函数,而应该用super();。

用new创建子类的对象时,若子类没有带参构造函数,将先执行父类的无参构造函数,然后再执行自己的构造函数。

子类的构造函数中可以调用其他函数。

A.java继承中对构造函数是不继承的,只是显式或者隐式调用,所以A选项不对
A、构造器不是继承,方法不说继承的。方法说的最多的就是重载和重写
B、C 子类构造器的第一行默认都是super(),但是一旦父类中没有无参构造,第一行必须显式的调用某一个有参构造
D、构造器中可以调用别的方法。

首先不管子类有没有 有参构造函数,在创建子类的对象的时候,若子类构造函数没有显式调用父类构造函数,就会先调用父类的无参构造函数;若是在子类的构造函数显式调用了父类的构造函数(包括有参的可以),则会先调用刚刚显示调用的父类构造函数。

362下面哪些情况下需要使用抽象类?ABD

当一个类的一个或多个方法是抽象方法时

当类是一个抽象类的子类,并且不能为任何抽象方法提供任何实现细节或方法体时

当一个类实现多个接口时

当一个类实现一个接口,并且不能为任何抽象方法提供实现细节或方法体时

抽象类:用abstract修饰,抽象类中可以没有抽象方法,但抽象方法肯定在抽象类中,且抽象方法定义时不能有方法体;抽象类不可以实例化只能通过继承在子类中实现其所有的抽象方法;抽象类如果加粗样式不被继承就没有任何意义;抽象类为子类定义了一个公共类型,封装了子类中的重复内容
接口:同Interface关键字定义接口,是特殊的抽象类因为类中只包含抽象方法;接口中不能定义成员变量可以定义常量;接口是其通过其他类使用implements关键字定义实现类,一个类一旦实现接口就必须实现其中的所有抽象方法,一个类可以实现多个接口,接口名之间用逗号隔开即可;一个接口可以通过extends关键字继承另一个接口,与此同时继承了父类中的所有方法。

A项 一个类中有抽象方法则必须声明为抽象类
B项 抽象类中的抽象方法必须由其子类实现,若子类不能实现则子类也必须定义为抽象类
D项 一个类实现一个接口就必须实现其中所有的抽象方法,若该实现类不能实现接口中的所有方法则实现类定义为抽象类

363 Java是一门支持反射的语言,基于反射为Java提供了丰富的动态性支持,下面关于Java反射的描述,哪些是错误的:( ADF )

Java反射主要涉及的类如Class, Method, Filed,等,他们都在java.lang.reflet包下

通过反射可以动态的实现一个接口,形成一个新的类,并可以用这个类创建对象,调用对象方法

通过反射,可以突破Java语言提供的对象成员、类成员的保护机制,访问一般方式不能访问的成员

Java反射机制提供了字节码修改的技术,可以动态的修剪一个类

Java的反射机制会给内存带来额外的开销。例如对永生堆的要求比不通过反射要求的更多

Java反射机制一般会带来效率问题,效率问题主要发生在查找类的方法和字段对象,因此通过缓存需要反射类的字段和方法就能达到与之间调用类的方法和访问类的字段一样的效率

A Class类在java.lang包
B 动态代理技术可以动态创建一个代理对象,反射不行
C 反射访问私有成员时,Field调用setAccessible可解除访问符限制
D CGLIB实现了字节码修改,反射不行
E 反射会动态创建额外的对象,比如每个成员方法只有一个Method对象作为root,他不胡直接暴露给用户。调用时会返回一个Method的包装类
F 反射带来的效率问题主要是动态解析类,JVM没法对反射代码优化。

364 下面有关java classloader说法错误的是? C

Java默认提供的三个ClassLoader是BootStrap ClassLoader,Extension ClassLoader,App ClassLoader

ClassLoader使用的是双亲委托模型来搜索类的

JVM在判定两个class是否相同时,只用判断类名相同即可,和类加载器无关

ClassLoader就是用来动态加载class文件到内存当中用的

比较两个类是否相等,只有这两个类是由同一个类加载器加载才有意义。否则,即使这两个类是来源于同一个Class文件,只要加载它们的类加载器不同,那么这两个类必定不相等。
补充:

  1. 什么是类加载器?

把类加载的过程放到Java虚拟机外部去实现,让应用程序决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。

  1. 有哪些类加载器,分别加载哪些类

类加载器按照层次,从顶层到底层,分为以下三种:
(1)启动类加载器 : 它用来加载 Java 的核心库,比如String、System这些类
(2)扩展类加载器 : 它用来加载 Java 的扩展库。

(3) 应用程序类加载器 : 负责加载用户类路径上所指定的类库,一般来说,Java 应用的类都是由它来完成加载的。

  1. 双亲委派模型

我们应用程序都是由以上三种类加载器互相配合进行加载的,还可以加入自己定义的类加载器。称为 类加载器的双亲委派模型 ,这里类加载器之间的父子关系一般不会以继承的关系来实现,而是都使用 组合关系 来复用父加载器的。

  1. 双亲委托模型的工作原理

是当一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法加载这个加载请求的时候,子加载器才会尝试自己去加载。

  1. 使用双亲委派模型好处?(原因)

第一:可以避免重复加载,当父亲已经加载了该类的时候,子类不需要再次加载。

第二:考虑到安全因素,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的类装载器。

365 对抽象类的描述正确的是(D)

抽象类的方法都是抽象方法

一个类可以继承多个抽象类

抽象类不能有构造方法

抽象类不能被实例化

解释:

A.抽象类可以有非抽象的方法,而接口中的方法都是抽象方法

B.java中类只能单继承,接口可以‘继承’多个接口

C.抽象类可以有构造方法,接口一定没有构造方法

D.实例化一般指new一个对象,所以抽象类不能实例化

366 What is the result? C

public class IfTest{
    public static void main(string[]args){
        int x=3;
        int y=1;
        if(x=y)
            System.out.println(“Not equal”);
        else
            System.out.println(“Equal”);
     }
}
The output is “Equal”

The output in “Not Equal”

An error at line 5 causes compilation to fall.

The program executes but does not print a message.

if()语句括号中为比较表达式,返回值要么是true,要么是false,if(x=y)是将y赋值给x,但是数据类型是int类型的,编译不能通过,如果把代码改为这样:
boolean x = false;
boolean y = ture;
if(x=y){…}这样就就不会报错了,编译正常通过。

1、Java中,赋值是有返回值的 ,赋什么值,就返回什么值。比如这题,x=y,返回y的值,所以括号里的值是1。
2、Java跟C的区别,C中赋值后会与0进行比较,如果大于0,就认为是true;而Java不会与0比较,而是直接把赋值后的结果放入括号。

367下列不属于Java语言性特点的是D

Java致力于检查程序在编译和运行时的错误

Java能运行虚拟机实现跨平台

Java自己操纵内存减少了内存出错的可能性

Java还实现了真数组,避免了覆盖数据类型的可能

程序设计语言中,数组元素在内存中是一个接着一个线性存放的,通过第一个元素就能访问随后的元素,这样的数组称之为“真数组”。
实现了真数组为Java语言健壮性的特点之一。
真数组: 数组元素在内存中是一个接着一个线性存放的,通过第一个元素就能访问随后的元素,避免了数据覆盖的可能性,和数据类型覆盖并没有关系。

Java致力于检查程序在编译和运行时的错误。
Java虚拟机实现了跨平台接口
类型检查帮助检查出许多开发早期出现的错误。
Java自己操纵内存减少了内存出错的可能性。
Java还实现了真数组,避免了覆盖数据的可能。
注意,是避免数据覆盖的可能,而不是数据覆盖类型

368 下列代码输出结果为( D )

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();
    }
}
动物可以移动
狗可以跑和走
狗可以吠叫

动物可以移动
动物可以移动
狗可以吠叫

运行错误

编译错误

编译看左边,运行看右边。 父类型引用指向子类型对象,无法调用只在子类型里定义的方法

编译错误:The method bark() is undefined for the type Animal。Animal中没有定义bark()方法。
Dog继承自Animal。
当用Dog对象初始化Animal类对象时,完成了对Animal对象中方法与变量的覆盖与隐藏,也就是b.move()调用的是Dog中move()方法。而Animal中本身并没有bark()方法,不存在被覆盖的情况,亦无法访问,也就是b.bark()会报错。

369 有如下4条语句:() 以下输出结果为false的是: C

Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);
System.out.println(i01==i02);

System.out.println(i01==i03);

System.out.println(i03==i04);

System.out.println(i02==i04);

①无论如何,Integer与new Integer不会相等。不会经历拆箱过程,
②两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false
java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
③两个都是new出来的,都为false
④int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比

牛客刷题笔记--(java基础301-400)_第16张图片

: ==比较的是地址
但是当为基本类型时,比较的是值,如果俩边有包装类型,则先将包装类型转换为基本类型在比较值是否相等。
当俩边都为包装类型时,即为对象,比较的是地址

Integer.valueOf方法中也有判断,如果传递的整型变量>= -128并且小于127时会返回IntegerCache类中一个静态数组中的某一个对象, 否则会返回一个新的Integer对象,代码如下

public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.***[i + (-IntegerCache.low)];
        return new Integer(i);
    }

所以如果你测试如下代码

public static void main(String[] args) {
		
		Integer a = 127;
		Integer b = 127;
		
		Integer c = 128;
		Integer d = 128;
		
		System.out.println(a == b);
		System.out.println(c == d);
	}

结合自动封装、常量池以及Integer.valueOf方法就不难得出,答案时true和false;
再看本题

	Integer i01=59;
	int i02=59;
	Integer i03=Integer.valueOf(59);
	Integer i04=new Integer(59);

第一行:由于59在-128~127范围之内,所以在自动装箱的时候,会返回IntegerCache[59 - (-128)];
第三行:同第一行
第四行:因为有new关键字,所以在heap中开辟了一块新内存放置值为59的Integer对象。

System.out.println(i01==i02);//正确
System.out.println(i01==i03);//正确,都指向IntegerCache[59-(-128)]对象
System.out.println(i03==i04);//错误,引用指向的对象地址不同
System.out.println(i02==i04);//正确

370 下列代码执行结果为(A)

下列代码执行结果为() 
public static void main(String args[])throws InterruptedException{
	    	Thread t=new Thread(new Runnable() {
				public void run() {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						throw new RuntimeException(e);
					}
					System.out.print("2");
				}
			});
	    	t.start();
	    	
	    	t.join();
	    	System.out.print("1");
	    }
21

12

可能为12,也可能为21

以上答案都不对

thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
t.join(); //使调用线程 t 在此之前执行完毕。
t.join(1000); //等待 t 线程,等待时间是1000毫秒

因为子线程的休眠时间太长,因此主线程很有可能在子线程之前结束也就是输出结果是12,但是子线程用了join函数,因此主线程必须等待子线程执行完毕才结束因此输出结果只能是21

join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。

371 java8中,下面哪个类用到了解决哈希冲突的开放定址法 C

LinkedHashSet

HashMap

ThreadLocal

TreeMap

ThreadLocalMap中使用开放地址法来处理散列冲突,而HashMap中使用的是分离链表法。之所以采用不同的方式主要是因为:在ThreadLocalMap中的散列值分散得十分均匀,很少会出现冲突。并且ThreadLocalMap经常需要清除无用的对象,使用纯数组更加方便。

threadlocal 使用开放地址法 - 线性探测法:当前哈希槽有其他对象占了,顺着数组索引寻找下一个,直到找到为止

hashset 中调用 hashmap 来存储数据的,hashmap 采用的链地址法:当哈希槽中有其他对象了,使用链表的方式连接到那个对象上

ThreadLocalMap通过key(ThreadLocal类型)的hashcode来计算数组存储的索引位置i。如果i位置已经存储了对象,那么就往后挪一个位置依次类推,直到找到空的位置,再将对象存放。另外,在最后还需要判断一下当前的存储的对象个数是否已经超出了阈值(threshold的值)大小,如果超出了,需要重新扩充并将所有的对象重新计算位置。

372对于线程局部存储TLS(thread local storage),以下表述正确的是ABD

解决多线程中的对同一变量的访问冲突的一种技术

TLS会为每一个线程维护一个和该线程绑定的变量的副本

每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了

Java平台的java.lang.ThreadLocal是TLS技术的一种实现

C:同一全局变量或者静态变量每个线程访问的是同一变量,多个线程同时访存同一全局变量或者静态变量时会导致冲突,尤其是多个线程同时需要修改这一变量时,通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。

ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证不同的线程都有一份拷贝。ThreadLocal 不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制.

如果是静态变量是共享的话,那必须同步,否则尽管有副本,还是会出错,故C错

373 通过HttpServletRequest. getParameter获取的参数. C

总是采用UTF-8编码

总是采用lS08859-1编码

由客户端浏览器和Web容器配置共同决定编码

由服务器所在的操作系统决定编码

1、浏览器根据jsp页面开头声明的编码方式对request中参数编码;
2、tomcat默认解码是ISO-8859-1, 但是我们可以显示指定解码格式通过调用 request.setCharacterEncoding(“UTF-8”),或者修改tomcat的配置文件server.xml中的编码,添加uriEncoding属性。

乱码问题之所以一直存在,就是由于编码的灵活性,也就是说,编码与其他工作是解耦的。此外,Web 的编码问题与服务器所在的操作系统无关,Web 容器诸如Tomcat可以配置默认编码方式,例如,Tomcat 的默认编码方式是 iso8859-1。乱码的解决之道就是直接或间接的使客户端与Web 容器编码方式兼容。

编码格式由浏览器决定,浏览器根据html中指定的编码格式进行编码,tomcat根据指定的格式进行解码,另外get请求和post请求对编码格式的处理也是不同的

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

Stacks

PC寄存器

Heap

Heap Frame

牛客刷题笔记--(java基础301-400)_第17张图片PC寄存器即程序计数器

375 保留的字符数为(C)
假定str0,…,str4后序代码都是只读引用。
Java 7中,以上述代码为基础,在发生过一次FullGC后,上述代码在Heap空间(不包括PermGen)保留的字符数为()

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;
5

10

15

20

解析:这是一个关于java的垃圾回收机制的题目。垃圾回收主要针对的是堆区的回收,因为栈区的内存是随着线程而释放的。堆区分为三个区:年轻代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法区)

年轻代:对象被创建时(new)的对象通常被放在Young(除了一些占据内存比较大的对象),经过一定的Minor GC(针对年轻代的内存回收)还活着的对象会被移动到年老代(一些具体的移动细节省略)。

年老代:就是上述年轻代移动过来的和一些比较大的对象。Minor GC(FullGC)是针对年老代的回收

永久代:存储的是final常量,static变量,常量池。

str3,str4都是直接new的对象,而substring的源代码其实也是new一个string对象返回,如下图:

经过fullgc之后,年老区的内存回收,则年轻区的占了15个,不算PermGen。所以答案选C

应该是C
substring实际是new,5字符
str3和4也都是new,每个5字符
分别都会创建新的对象
常量池是PermGen的
因此应该是一共15字符

376 下面这段java代码,当 T 分别是引用类型和值类型的时候,分别产生了多少个 T对象和T类型的值(D)

T t = new T();(值类型时:T t;)
Func(t);
Func 定义如下:
public void Func(T t) {  }
1  1

2  1

2  2

1  2

引用类型作为函数的参数时,复制的是引用的地址,不会产生一个新的T;而如果T是值类型,其作为函数实参时会复制其值,也就是产生了一个新的T

这个题考查的应该是 Java 中只有值传递。

对于引用类型来说,传参时传递的是引用类型的值,会在方法的栈帧中创建一个引用类型的变量,接收传递过来的值,但是两个变量指向的是堆内存中同一个对象,所以只创建了一个 T 对象的值。

对于基本类型来说,传参时直接传递基本类型的值,所以会创建两个 T 类型的值。

377 关于Java内存区域下列说法不正确的有哪些 BC

程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器,每个线程都需要一个独立的程序计数器.

Java虚拟机栈描述的是java方法执行的内存模型,每个方法被执行的时候都会创建一个栈帧,用于存储局部变量表、类信息、动态链接等信息

Java堆是java虚拟机所管理的内存中最大的一块,每个线程都拥有一块内存区域,所有的对象实例以及数组都在这里分配内存。

方法区是各个线程共享的内存区域,它用于存储已经被虚拟机加载的常量、即时编译器编译后的代码、静态变量等数据。

B.类信息不是存储在java虚拟机栈中,而是存储在方法区中;
C.java堆是被所有线程共享的一块内存区域,而不是每个线程都拥有一块内存区域。
A.程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器(偏移地址),Java编译过程中产生的字节码有点类似编译原理的指令,程序计数器的内存空间存储的是当前执行的字节码的偏移地址,每一个线程都有一个独立的程序计数器(程序计数器的内存空间是线程私有的),因为当执行语句时,改变的是程序计数器的内存空间,因此它不会发生内存溢出 ,并且程序计数器是jvm虚拟机规范中唯一一个没有规定 OutOfMemoryError 异常 的区域;

B.java虚拟机栈:线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。 没有类信息,类信息是在方法区中

C.java堆:对于绝大多数应用来说,这块区域是 JVM 所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组

D.方法区:属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
378 下面语句正确的是(D)

x+1=5

i++=1

a++b=1

x+=1

赋值运算符左侧必须为变量

总结一下: 1-首先赋值运算符“=”右值可以是任何常数、变量或者表达式(只要能生成一个值就行)。但左值必须是一个明确的、已命名的变量。 2-常用的双元运算符:+=,-=,*=,/= 解析: A:x+1=5,赋值运算符左边是表达式,不对; B:i++=1,从左到右运算是i=i+1=1,赋值运算符左边是表达式,错误; C:a++b=1,赋值运算符左边为表达式,错误。D:x+=1,既x=x+1,正确。 注意背一下各个运算符的先后顺序。

379 下列说法正确的是(B)

在类方法中可用this来调用本类的类方法

在类方法中调用本类的类方法时可直接调用

在类方法中只能调用本类中的类方法

在类方法中绝对不能调用实例方法

B :类方法是指用static修饰的方法,普通方法叫对象方法。 A.this指的是当前对象,类方法依附于类而不是对象this会编译出错 C.类方法中也可以调用其他类的类方法。同时可以通过创建对象来调用普通方法 D.类方法中可以创建对象,所以可以调用实例方法

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

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

2

1

-2

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

381下面程序的运行结果:(B)

public static void main(String args[]) {
		Thread t=new Thread(){
		public void  run(){
			dianping();
			
		}
	};
	t.run();
	System.out.print("dazhong");
	}
	static void dianping(){
		System.out.print("dianping");
}
dazhongdianping

dianpingdazhong

a和b都有可能

dianping循环输出,dazhong夹杂在中间

在上面main()方法中,并没有创建一个新的线程,只是简单地方法调用而已,如果想要创建线程,需要t.start();创建线程,等待cpu时间片,而run()方法只是简单地方法调用,所以先执行run(),再输出dazhong

如果调用run() 选b
如果调用start() 选c
因为调用start后并不保证线程启动的顺序

这里仅仅是调用了run()方法,程序就只能顺序执行;开启线程是调用start()方法,这样才能并发执行。

382 对文件名为Test.java的java代码描述正确的是©

class Person {
	String name = "No name";
	public Person(String nm) {
		name = nm;
	}
}
class Employee extends Person {
	String empID = "0000";
	public Employee(String id) {
		empID = id;
	}
}
public class Test {
	public static void main(String args[]) {
		Employee e = new Employee("123");
		System.out.println(e.empID);
	}
}
输出:0000

输出:123

编译报错

输出:No name

父类没有无参的构造函数,所以子类需要在自己的构造函数中显式调用父类的构造函数,
添加
super(“nm”);
否则报错:
Implicit super constructor Person() is undefined. Must explicitly invoke another constructor

子类的构造方法总是先调用父类的构造方法,如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类不带参数的构造方法
而父类没有无参的构造函数,所以子类需要在自己的构造函数中显示的调用父类的构造函数

383 表达式(short)10/10.2*2运算后结果是什么类型?C

short

int

double

float

首先,要注意是(short)10/10.22,而不是(short) (10/10.22),前者只是把10强转为short,又由于式子中存在浮点数,所以会对结果值进行一个自动类型的提升,浮点数默认为double,所以答案是double;后者是把计算完之后值强转short。

384 在Web应用程序中,( )负责将HTTP请求转换为HttpServletRequest对象C

Servlet对象

HTTP服务器

Web容器

JSP网页

web容器是一种服务程序,在服务器一个端口就有一个提供相应服务的程序,而这个程序就是处理从客户端发出的请求,如JAVA中的Tomcat容器,ASP的IIS或PWS都是这样的容器。一个服务器可以多个容器。

Apache就是一个Http服务器,Tomcat是一个web容器,静态的htmlApache还可以处理,但是动态的需要转发给Tomcat去处理了,比如jsp页面,请求先经由Apache转发给Tomcat再由Tomcat解析请求。所以应该是web容器去解析成request对象。

servlet是运行在服务器端的小应用程序,是接收网络服务的请求和产生响应的一种方式。
servlet的功能:接受http请求,产生动态http响应。

385 在 myjsp.jsp 中,关于下面的代码说法错误的是: ( A)
<%@ page language=“java” import=“java.util.*” errorPage=“error.jsp” isErrorPage=“false” %>

该页面可以使用 exception 对象

该页面发生异常会转向 error.jsp

存在 errorPage 属性时,isErrorPage 是默认为 false

error.jsp 页面一定要有isErrorPage 属性且值为 true

exception是JSP九大内置对象之一,其实例代表其他页面的异常和错误。只有当页面是错误处理页面时,即isErroePage为 true时,该对象才可以使用。对于C项,errorPage的实质就是JSP的异常处理机制,发生异常时才会跳转到 errorPage指定的页面,没必要给errorPage再设置一个errorPage。所以当errorPage属性存在时, isErrorPage属性值为false

当isErrorPage ="false"时,用errorPage=“error.jsp”(isErrorPage默认是false)
当isErrorPage ="true"时,页面会直接使用exception

errorPage 的意思是设置当前页面要引入错误的页面。也就是浮面当前页面如果出现错误就会跳转到errorPage所指定的页面。
isErrorpage 的意思是当前页面为错误页面。
isErrorPage默认值为false,若要当前页面为错误页面就设置isErrorPage=true。

386 下列整型常量 i 的定义中,正确的是( C )

final i;

static int i;

static final int  i=234;

final float i=3.14f;

因为是整型所以要申明 int
所以A D不对又因为是常量所以 要用final限制所以答案 C

题目中有要求是‘整型’‘常量’ ,所以int final这两个关键字必须有,而被final修饰的常量必须赋值,所以选C

== java中final修饰的变量有三种:静态变量、实例变量和局部变量==,分别表示三种类型的常量。int关键字修饰整型类型。static修饰静态变量,即当利用这个关键字来修饰一个变量的时候,在创建对象之前就会为这个变量在内存中创建一个存储空间。以后创建对对象如果需要用到这个静态变量,那么就会共享这一个变量的存储空间。
A:缺少必要的整型类型声明
B:缺少常量关键字final
D:定义一个浮点常量

387 以下Java程序运行的结果是:A

public class Tester{
public static void main(String[] args){
   Integer var1=new Integer(1);
   Integer var2=var1;
   doSomething(var2);
   System.out.print(var1.intValue());
   System.out.print(var1==var2);
}
public static void doSomething(Integer integer){
    integer=new Integer(2);
    }
}
1true

2true

1false

2false

Java中处理8种基本的数据类型用的是值传递,其他所有类型都用的是引用传递,由于这8种基本数据类型的包装类型都是不可变类,因此增加了对“按引用传递”的理解难度。其实还是很好理解的,题目中doSomething方法中new了一个对象,这是误导大家选择答案C的原因。其实,按引用传递的实质是将地址值的副本作为实参代替方法中的形参,因此var2与var1里面存储的地址值仍然是一样的,方法中操作的只是var2的一个副本值,并不影响var2本身存储的地址值,所以答案选择A。

牛客刷题笔记--(java基础301-400)_第18张图片
388 Java 提供的事件处理模型是一种人机交互模型。它有三个基本要素 ABD

事件源

事件对象

事件过程

事件监听器

解释:
面向对象的语言里没有“过程”
面向过程的语言里没有“对象”

Java 提供的事件处理模型是一种人机交互模型。它有三个基本要素:

  1. 事件源(Event Source):即事件发生的场所,就是指各个组件,如按钮等,点击按钮其实就是组件上发生的一个事件;

  2. 事件(Event):事件封装了组件上发生的事情,比如按钮单击、按钮松开等等;

  3. 事件***(Event Listener):负责监听事件源上发生的特定类型的事件,当事件到来时还必须负责处理相应的事件;

389 true、false、null、sizeof、goto、synchronized 哪些是Java关键字?EF

true

false

null

sizeof

goto

synchronized

牛客刷题笔记--(java基础301-400)_第19张图片
1,Java 关键字列表 (依字母排序 共50组):
abstract, assert, boolean, break, byte, case, catch, char, class, const(保留关键字), continue, default, do, double, else, enum, extends, final, finally, float, for, goto(保留关键字), if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while
2,保留字列表 (依字母排序 共14组),Java保留字是指现有Java版本尚未使用,但以后版本可能会作为关键字使用
byValue, cast, false, future, generic, inner, operator, outer, rest, true, var, goto (保留关键字) , const (保留关键字) , null

java的关键字对Java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名、方法名、类名、包名和参数
true false 是boolean的变量值,是编译器赋予特定含义的,但并不是关键字

390 以下代码将打印出 B

	public static void main(String args[]) {
		  List  Listlist1 = new ArrayList();
		  Listlist1.add(0);
		  List Listlist2 = Listlist1;
		    System.out.println(Listlist1.get(0) instanceof Integer);
		    System.out.println(Listlist2.get(0) instanceof Integer);
	}
编译错误

true true

true false

false false

collection类型的集合(ArrayList,LinkedList)只能装入对象类型的数据,该题中装入了0,是一个基本类型,但是JDK5以后提供了自动装箱与自动拆箱,所以int类型自动装箱变为了Integer类型。编译能够正常通过。
将list1的引用赋值给了list2,那么list1和list2都将指向同一个堆内存空间。instanceof是Java中关键字,用于判断一个对象是否属于某个特定类的实例,并且返回boolean类型的返回值。显然,list1.get(0)和list2.get(0)都属于Integer的实例

答案B 不指定ArrayList类型,存入数据,再次取出时,默认是Object类型;但这个题的关键是instanceof关键字,instanceof执行时类似利用java反射机制,识别对象信息。

List集合中的元素必须是对象。
Listlist1.add(0);JDK1.5之后支持自动装箱(int类型自动装箱成Integer),编译通过。

instanceof:前一个参数通常是一个引用类型变量,后一个操作数通常是一个类(也可以是一个接口, 它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。

List没有使用泛型,说明使用get(0)取出的元素的编译类型是Object型的, 但运行时类型是Integer。所以打印true。这便体现了多态。
而Listlist1把引用赋给了List list2,说明两个指向同一个对象。第二个打印的也是true。

391 变量a是一个64位有符号的整数,初始值用16进制表示为:0x7FFFFFFFFFFFFFFF;变量b是一个64位有符号的整数,初始值用16进制表示为:0x8000000000000000。则a+b的结果用10进制表示为多少?B

1

-1

2^63+2^62++2^2+2^1+2^0(2^63+2^62++2^2+2^1+2^0)

(1)a+b的16进制表示为:OxFFFFFFFFFFFFFFF(16位F),转为2进制为111……111(64位1,每个F->4位2)。
(2)有符号数:是针对二进制来讲的。用最高位作为符号位,“0”代表“+”,“1”代表“-”。所以a+b的结果是一个负数。
(3)计算机中负数是以补码的形式保存的,将补码转换成原码的计算方式如下:
①. 对于正数,原码与补码相同。
②.对于负数,将补码除符号位之外,按位取反,末位加1,即得到原码。
(4)a + b = 111……111(64位1)
取反:100……000(1位1,后面63位0)
加一:100……00(中间62位0)
10进制:-1。

392 java中Hashtable, Vector, TreeSet, LinkedList哪些线程是安全的?AB

Hashtable

Vector

TreeSet

LinkedList

Hashtable是线程安全的HashMap
Vector是线程安全的ArrayList
TreeSet和LinkedList都不是线程安全的

线程安全概念:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

线程安全问题都是由全局变量及静态变量引起的

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

牛客刷题笔记--(java基础301-400)_第20张图片
LinkedList 和 ArrayList 都是不同步的,线程不安全;
Vector 和 Stack 都是同步的,线程安全;
Set是线程不安全的;

Hashtable的方法是同步的,线程安全;
HashMap的方法不是同步的,线程不安全;

简单记忆线程安全的集合类: 喂! SHE ! 喂是指 vector , S 是指 stack , H 是指 hashtable , E 是指: Eenumeration

393 判断一块内存空间是否符合垃圾收集器收集的标准有哪些?ABD

给对象赋予了空值null,以下再没有调用过

对象重新分配了内存空间

给对象赋予了空值null

给对象赋予了新值

在java语言中,判断一块内存空间是否符合垃圾收集器收集标准的标准只有两个:
1.给对象赋值为null,以下没有调用过。
2.给对象赋了新的值,重新分配了内存空间。

Cat obj=new Cat();
obj=null;//这个应该叫对象的引用置为了null,回收的是之前new Cat()时申请到的内存
obj=new Cat();//这个叫对象引用重新指向了另外一个对象,赋予了新值,回收的是上次new Cat()的内存
应该是这么理解吧

394 在 Java 中,存放字符串常量的对象属于( B)类对象。

Character

String

StringBuffer

Vector

Character 字符封装类
String 常量池中字符串
StringBuffer 存放字符数组
Vector 数组
存放字符串的可以为String和StringBuffer,前者定义的字符串不可变,后者可变,Character为字符型的包装类型
Vector与ArrayList类似,都实现了list接口,内部都是通过数组实现的,但是Vector支持线程的同步,避免了多线程引起的不一致性

生成字符串的两个类String和StringBuffer中,前者生成的字符串是不变字符串,不能直接对它的内容进行修改,而后者生成的字符串是可变的,可以对其内容进行修改。而Character类是对字符类型的类封装。Vector类是Java语言提供给用户的一种通用类,是一种链表结构的类型。

395 下面的程序 编译运行后,在屏幕上显示的结果是(A)

 public class test {

public static void main(String args[]) {

int x,y;

x=5>>2;

y=x>>>2;
System.out.println(y);
}
} 

5 >> 2 相当于 5除于2的平方,等于1 ,>>> 表示无符号 右移,高位用0 填充,0001 右移两位 0000,所以答案选 A

Java中的位运算符:

>>表示右移,如果该数为正,则高位补0,若为负数,则高位补1>>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0

5的二进制是0101。

x=5>>2 (>>带符号右移)
将0101右移2位,为:0001。

y=x>>>2 (>>>无符号右移,左边空缺补充为0)

将0001右移2位,补0。结果为:0000。

所以得出答案0

这道题首先要知道二进制的计算方式
举例:0011
二进制换算十进制,从右到左,以当前位数字 乘以 2 的索引字幂,然后相加,索引从0开始计算。
如:

右一数字为1,索引为0。所以为:1*2^0(1乘以2的0次方)

右二数字为1,索引为1。所以为:1*2^1(1乘以2的1次方)

右三数字为0,索引为2。所以为:0*2^2(0乘以2的2次方)

右四数字为0,索引为3。所以为:0*2^3(0乘以2的3次方)

最后把结果相加。所以计算方式为:

023+0*22+121+1*20

=0+0+2+1

=3

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

位

字节

字

双字

位<字节<字<双字
1双字=2字=4字节=32位
位、字节、字是计算机数据存储的单位。位是最小的存储单位,每一个位存储一个1位的二进制码,一个字节由8位组成。而字通常为16、32或64个位组成。

397 执行语句“int a= ’ 2 ’ ”后,a的值是( B)

2

50

49

0

常用ASCII码值:空格为32;数字0为48;“A”为65;“a”值为97。
常见字符的ASCII码值如下:空格的ASCII码值为32;数字0到9的ASCII码值分别为48到57;大写字母“A”到“Z”的ASCII码值分别为65到90;小写字母“a”到“z”的ASCII码值分别为97到到122。

398 下面不是面向对象的基本原则的是?C

单一职责原则(Single-Resposibility Principle)

开放封闭原则(Open-Closed principle)

抽象类原则(Abstract-Class principle)

依赖倒置原则(Dependecy-Inversion Principle)

接口隔离原则(Interface-Segregation Principle)

s( Single-Resposibility Principle ): 单一职责原则
o( Open-Closed principle ): 开放封闭原则
l( Liskov-Substituion Principle ): 里氏原则
i( Interface-Segregation Principle ): 接口隔离原则
d( Dependecy-Inversion Principle ): 依赖倒置原则
一个单词:立方体(solid),很好记!!!

五个基本原则:
单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。
Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。
依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。
接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口

399 说明输出结果。 C

package test; 
import java.util.Date;  
public class SuperTest extends Date{  
    private static final long serialVersionUID = 1L;  
    private void test(){  
       System.out.println(super.getClass().getName());  
    }  
     
    public static void main(String[]args){  
       new SuperTest().test();  
    }  
}  
SuperTest

SuperTest.class

test.SuperTest

test.SuperTest.class

TestSuper和Date的getClass都没有重写,他们都是调用Object的getClass,而Object的getClass作用是返回的是运行时的类的名字。这个运行时的类就是当前类,所以

super.getClass().getName()

返回的是test.SuperTest,与Date类无关
要返回Date类的名字需要写super.getClass().getSuperclass()

1.首先 super.getClass() 是父类的getClass()方法,其父类是Date,它的getClass()方法是继承自Object类而且没有重写,
所以就是调用object的getClass()方法。而看一下getclass的方法解释如下图
在这里插入图片描述

所以可以知道是返回当前运行时的类。

2.==在调用getName()方法而getName()是:包名+类名 ==

super.getClass().getName()
返回:包名+类名

400 如下哪些是 java 中有效的关键字(AD)

native

NULL

false

this

这个关键字常见的坑:
true、false不是关键字,而是保留字
goto、const、是保留的关键字
null是java中的关键字,但是本题中大写的NULL就不是了

你可能感兴趣的:(Java)