牛客网上面的360笔试题 Java工程师
- 执行以下程序后的输出结果是()
public static void main(String[] args) {
StringBuffer a = new StringBuffer("A");
StringBuffer b = new StringBuffer("B");
operator(a, b);
System.out.println(a + "," + b);
}
public static void operator(StringBuffer x, StringBuffer y) {
x.append(y); y = x;
}
}
A。A,A
B。A,B
C。B,B
D。AB,B
答案:D
解析:
StringBuffer a = newStringBuffer(“A”);
StringBuffer b = newStringBuffer(“B”);
此时内存中的状态如下图所示:
publicstaticvoidoperator(StringBuffer x, StringBuffer y) {
x.append(y); y = x;
}
进入如下方法后,内存中的状态为:
x.append(y);
这条语句执行后,内存的状态为:
y = x;
这条语句执行后,内存的状态为:
当operator方法执行完毕后内存中的状态为:因为方法执行完毕,局部变量消除。
2.结构型模式中最体现扩展性的模式是()
A。装饰模式
B。合成模式
C。桥接模式
D。适配器
答案:A
解析:
结构型模式是描述如何将类对象结合在一起,形成一个更大的结构,结构模式描述两种不同的东西:类与类的实例。故可以分为类结构模式和对象结构模式。
在GoF设计模式中,结构型模式有:
1.适配器模式 Adapter
适配器模式是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
两个成熟的类需要通信,但是接口不同,由于开闭原则,我们不能去修改这两个类的接口,所以就需要一个适配器来完成衔接过程。
2.桥接模式 Bridge
桥接模式将抽象部分与它的实现部分分离,是它们都可以独立地变化。它很好的支持了开闭原则和组合锯和复用原则。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这些多角度分离出来让他们独立变化,减少他们之间的耦合。
3.组合模式 Composite
组合模式将对象组合成树形结构以表示部分-整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
4.装饰模式 Decorator
装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,它比生成子类更灵活。也可以这样说,装饰模式把复杂类中的核心职责和装饰功能区分开了,这样既简化了复杂类,有去除了相关类中重复的装饰逻辑。 装饰模式没有通过继承原有类来扩展功能,但却达到了一样的目的,而且比继承更加灵活,所以可以说装饰模式是继承关系的一种替代方案。
5.外观模式 Facade
外观模式为子系统中的一组接口提供了同意的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式中,客户对各个具体的子系统是不了解的,所以对这些子系统进行了封装,对外只提供了用户所明白的单一而简单的接口,用户直接使用这个接口就可以完成操作,而不用去理睬具体的过程,而且子系统的变化不会影响到用户,这样就做到了信息隐蔽。
6.享元模式 Flyweight
享元模式为运用共享技术有效的支持大量细粒度的对象。因为它可以通过共享大幅度地减少单个实例的数目,避免了大量非常相似类的开销。.
享元模式是一个类别的多个对象共享这个类别的一个对象,而不是各自再实例化各自的对象。这样就达到了节省内存的目的。
7.代理模式 Proxy
为其他对象提供一种代理,并由代理对象控制对原对象的引用,以间接控制对原对象的访问。
3.在Linux中,对file.sh文件执行#chmod 645 file.sh中,该文件的权限是()
A。-rw-r–r--
B。-rw-r–rx-
C。-rw-r–rw-
D。-rw-r–r-x
答案:D
解析:
文件和目录的权限表示,是用rwx这三个字符来代表所有者、用户组和其他用户的权限。有时候,字符似乎过于麻烦,因此还有另外一种方法是以数字来表示权限,而且仅需三个数字。
r: 对应数值4
w: 对应数值2
x:对应数值1
-:对应数值0
数字设定的关键是mode的取值,一开始许多初学者会被搞糊涂,其实很简单,我们将rwx看成二进制数,如果有则有1表示,没有则有0表示,那么-rw- r–r-x则可以表示成为:
110 100 101
再将其每三位转换成为一个十进制数,就是645。
4.TCP建立连接的过程采用三次握手,已知第三次握手报文的发送序列号为1000,确认序列号为2000,请问第二次握手报文的发送序列号和确认序列号分别为
A。1999,999
B。1999,1000
C。999,2000
D。999,1999
答案:B
解析:
简化一下,其实有两个序列,客户端发送X,服务器发送Y。三次握手分别是
客户端:发送X
服务端:发送Y, 确认X+1
客户端:发送X+1(1000),确认Y+1(2000)
可以反推第二次为1999,确认1000
5.下列TCP连接建立过程描述正确的是:
A。服务端收到客户端的SYN包后等待2ml时间后就会进入SYN_SENT状态
B。服务端收到客户端的ACK包后会进入SYN_RCVD状态
C。当客户端处于ESTABLISHED状态时,服务端可能仍然处于SYN_RCVD状态
D。服务端未收到客户端确认包,等待2ml时间后会直接关闭连接
答案:C
解析:
A:SYN_SENT是客户端发送SYN包之后的立即进入的状态,不用等待2ml
B:服务端收到客户端的SYN包后会进入SYN_RCVD状态,服务端收到ACK包后会进入established状态。
C: 当客户端处于ESTABLISHED状态时,服务端等待接收客户端的ACK,所以可能处于SYN_RCVD状态。
D: 客户端收到服务端确认包后,等待2*ml时间后会直接关闭连接。若没有收到,则不会关闭连接。
6.属于网络112.10.200.0/21的地址是()
A。112.10.206.0
B。112.10.217.0
C。112.10.224.0
D。112.10.198.0
答案:A
解析:
前21位为网络地址,后12位为主机地址。
112 对应前8位,10对应第二个8位,因此200对应第3个8位
又200的二进制表示为1100 1000
前面已经有了16位,因此11001 是属于网络地址的。000是属于主机地址 那么,最大的地址为
【112(十进制)】【10(十进制)】【11001 111】【 11111111】转换为十进制为112.10.207.255
故网络的地址范围为
112.10.200.0~112.10.207.255
- 以下java程序代码,执行后的结果是()
java.util.HashMap map=new java.util.HashMap();
map.put("name",null);
map.put("name","Jack");
System.out.println(map.size());
A。0
B。null
C。1
D。2
答案:C
解析:
HashMap可以插入null的key或value,插入的时候,检查是否已经存在相同的key,如果不存在,则直接插入,如果存在,则用新的value替换旧的value,在本题中,第一条put语句,会将key/value对插入HashMap,而第二条put,因为已经存在一个key为name的项,所以会用新的value替换旧的vaue,因此,两条put之后,HashMap中只有一个key/value键值对。那就是(name,jack)。所以,size为1.
- 以下java程序代码,执行后的结果是()
public class Test {
public static void main(String[] args) {
Object o = new Object() {
public boolean equals(Object obj) {
return true;
}
};
System.out.println(o.equals("Fred"));
}
}
A。Fred
B。true
C。编译错误
D。运行时抛出异常
答案:B
解析:
重写了object 的equals 的方法,使他怎么输出都是true
- 代码片段:
byte b1=1,b2=2,b3,b6;
final byte b4=4,b5=6;
b6=b4+b5;
b3=(b1+b2);
System.out.println(b3+b6);
关于上面代码片段叙述正确的是()
A。输出结果:13
B。语句:b6=b4+b5编译出错
C。语句:b3=b1+b2编译出错
D。运行期抛出异常
答案:C
解析:
被final修饰的变量是常量,这里的b6=b4+b5可以看成是b6=10;在编译时就已经变为b6=10了
而b1和b2是byte类型,java中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过,需要进行强制转换。
Java中的byte,short,char进行计算时都会提升为int类型。
- 下面代码运行结果是()
public class Test{
public int add(int a,int b){
try {
return a+b;
}
catch (Exception e) {
System.out.println("catch语句块");
}
finally{
System.out.println("finally语句块");
}
return 0;
}
public static void main(String argv[]){
Test test =new Test();
System.out.println("和是:"+test.add(9, 34));
}
}
A。catch语句块
和是:43
B。编译异常
C。finally语句块
和是:43
D。和是:43
finally语句块
答案:c
解析:
System.out.println(“和是:”+test.add(9, 34)); 这是进行字符串拼接是一个整体,所以首先是进入add方法中,进去之后先把先不运算result,而是输出finally块。注意:此时finally块输出结果是:finally语句块,这句话首先打印到控制台中。打印完后返回来执行try中的return得到43,所以此时再将结果与"和是:"进行拼接–>输出:和是 43。所以此时控制台又多了一句话:和是 43。加上之前finally先在控制台上的输出,所以结果为:finally语句块 和是 43.
先来看一段代码:
public abstract class Test {
public static void main(String[] args) {
System.out.println(beforeFinally());
}
public static int beforeFinally(){
int a = 0;
try{
a = 1;
return a;
}finally{
a = 2;
}
}
}
/**output:
1
*/
从结果上看,貌似finally 里的语句是在return 之后执行的,其实不然,实际上finally 里的语句是在在return 之前执行的。那么问题来了,既然是在之前执行,那为什么a 的值没有被覆盖了?
实际过程是这样的:当程序执行到try{}语句中的return方法时,它会干这么一件事,将要返回的结果存储到一个临时栈中,然后程序不会立即返回,而是去执行finally{}中的程序, 在执行a = 2时,程序仅仅是覆盖了a的值,但不会去更新临时栈中的那个要返回的值 。执行完之后,就会通知主程序“finally的程序执行完毕,可以请求返回了”,这时,就会将临时栈中的值取出来返回。这下应该清楚了,要返回的值是保存至临时栈中的。
11.以下情况下不一定出现TCP分节RST的情况是:
A。服务器端端口未打开而客户端来连接时
B。SO_RCVTIMEO选项设置了超时时间并超时
C。服务器主机崩溃后重启
D。在一个已关闭的socket上收到数据
答案:C
解析:
四种情况会发送RST包:
1、端口未打开
2、请求超时
3、提前关闭
4、在一个已关闭的socket上收到数据
12.一个数据库中现有A,B,C,D,E,F六个语句但目前这个数据库是不协调的,必须删除某些语句才能恢复数据库的协调性。已知:(1)如果保留语句A,那么必须保留语句B和C。(2)如果保留语句E,则必须同时删除语句D和语句C。(3)只有保留语句E,才能保留语句F。(4)语句A是重要的信息,不能删除。以上各项如果为真,则以下哪项一定为真?
A。保留语句E并且删除语句D
B。保留语句E并且删除语句C
C。同时保留语句C和语句D
D。同时删除语句E和语句F
答案:D
解析:
根据(4),A必须有;
再根据(1),B,C必须有,此时一定有ABC
根据(2),因为有C,所以一定没有E
根据(3),因为没有E,所以一定没有F
综上,ABC一定有,EF一定没有,D不确定
13.下列关于静态工厂和工厂方法表述错误的是:()
A。在工厂方法模式中,对于存在继承等级结构的产品树,产品的创建是通过相应等级结构的工厂创建的
B。不能形成静态工厂的继承结构
C。静态工厂对具体产品的创建类别和创建时机的判断是混和在一起的,这点在工厂方法中
D。二者都满足开闭原则:静态工厂以if else方式创建对象,增加需求的时候会修改源代码
答案:D
解析:
开闭原则:对扩展开放,对修改封闭。静态工厂(简单工厂)增加需要是修改源代码,对修改不封闭,不符合开闭原则。
14.设有一个用数组Q[1…m]表示的环形队列,约定f为当前队头元素在数组中的位置,r为队尾元素的后一位置(按顺时针方向),若队列非空,则计算队列中元素个数的公式应为()
A。(m+r-f)mod m
B。r-f
C。(m-r-f)mod m
D。(m-r+f)mod m
答案:A
解析:
用尾减去头 ,加上MAXSIZe是为了防止 头的地址大于尾
- 以下程序是用辗转相除法来计算两个非负数之间的最大公约数:
long long gcd(long long x,long long y){
if(y==0)
return x;
else return gcd(y,x%y);
}
我们假设x,y中最大的那个数的长度为n,基本基本运算时间复杂度是O(1),那么该程序的时间复杂度为()
A。O(logn)
B。O(1)
C。O(n^2)
D。O(n)
答案:A
解析:
快速的思路是排除法,不是与固定几个值计算,所以不是O(1)的,当然也不会把每个数都遍历个遍来确定,不是O(n)和O(n^2)的
- 计算斐波那契数列第n项的函数定义如下:
int fib(int n){
if(n==0)
return 1;
else if(n==1)
return 2;
else
return fib(n-1)+fib(n-2);
}
若执行函数调用表达式fib(10),函数fib被调用的次数是:
A。117
B。137
C。157
D。177
答案:D
解析:
定义g(n)函数表示计算fib(n)而调用的fib函数的次数
则
g(10) = g(9) + g(8) + 1(1是调用fib(10)需要执行一次fib函数)
。。。。
g(2) = g(1) + g(0) + 1
g(1) = 1
g(0) = 1
设图G的相邻矩阵如下图:则G的顶点数和边数分别为:
0 1 1 1 1
1 0 1 0 0
1 1 0 1 1
1 0 1 0 1
1 0 1 1 0
A。4,5
B。4,10
C。5,6
D。5,8
答案:D
解析:
矩阵为5*5,则有五个顶点;
关于主对角线对称,则为无向图;
无向图中,边数目等于上/下三角矩阵中的非零元素数目。