牛客刷题笔记--(java基础51-100)

51 以下代码返回值是什么?

public boolean returnTest() { try { return true; } catch (Exception e) {} finally { return false; } }

答案:false
==解释: 一旦在finally块中使用了return或throw语句,将会导致try块,catch块中的return,throw语句失效 ==
finally其实是仅在return 语句执行前执行,如果return 一个函数,那么会先执行函数,但如果函数内有(return)语句,那么finally就会在这个return 语句前执行。finally在catch中的return之前执行但是如果catch中有返回值而finally中也有返回值的话finally中的返回值会替换catch中的返回值,因为catch中的返回值是存放在一个临时区中。
如果catch块有异常向外抛出,执行顺序呢:我执行我的,你抛你得异常,我finally我的语句,我俩互不干涉,你别管我啥时执行,但我一定会执行。
关于finally,您只需记着一点:除非调用system.exit()让程序退出(也就是将调用这个程序的进程断开了、退出了这个程序)就不会执行或断电等因素致使程序停止进程终止,否则,无论任何因素,finally块都一定会执行。
在Java中规定,多行注释可以嵌套单行注释,但是不能嵌套多行注释
52 下列不正确的 Java 语言标识符是(C )
Sky
$Computer
for
NULL
Java标识符命名规范是:
1)只能包含字母a-zA-Z,数字0-9,下划线_和美元符号$;
2)首字母不能为数字;
3)关键字和保留字不能作为标识符。
null是关键字,NULL不是关键字,java区分大小写。这题答案D是对的,但C是错的,for是关键字。
标识符就是用于Java程序中变量,类,方法等命名的符号,Java标识符不能是Java关键字,还有区分大小写, 还有,标识符可以由字母,数字,下划线,$组成,不能包含@,%,空格,不以数字开头,,,NULL和null不一样啊
53 正则表达式中,表示匹配非数字字符的字符是(D)?
\b
\d
\B
\D
解释: \b匹配一个单词边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\d 是数字的意思,\D是非数字的意思
54 以下哪些方法是Object类中的方法(ABCD)
clone()
toString()
wait()
finalize()
全选,Object 类中方法及说明如下:
registerNatives() //私有方法
getClass() //返回此 Object 的运行类。
hashCode() //用于获取对象的哈希值。
equals(Object obj) //用于确认两个对象是否“相同”。
clone() //创建并返回此对象的一个副本。
toString() //返回该对象的字符串表示。
notify() //唤醒在此对象监视器上等待的单个线程。
notifyAll() //唤醒在此对象监视器上等待的所有线程。
wait(long timeout) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或 者超过指定的时间量前,导致当前线程等待。
wait(long timeout, int nanos) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。
wait() //用于让当前线程失去操作权限,当前线程进入等待序列
finalize() //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
牛客刷题笔记--(java基础51-100)
文章图片

55 要在session对象中保存属性,可以使用以下哪个语句( )
答:session.setAttribute(“key”,”value”)
解释: 获取属性用getAttribute 保存属性用setAttribute
属性是一个键值对,要把键值对内容都传递进去

session.getAttribute(“key”,“value”)
获取
session.getAttribute(“key”)
移除
session.removeAttribute(“key”)
56 方法通常存储在进程中的哪一区(D)
堆区
栈区
全局区
方法区
1.栈区:存放函数的参数、局部变量等
2.堆区:存放对象
3.全局区(静态区):存放全局变量和静态变量
4.常量区:存放常量字符串
5.代码区:存放函数体的二进制代码
57 以下程序的运行结果是?(A)
牛客刷题笔记--(java基础51-100)
文章图片

foobar
barfoo
foobar或者barfoo都有可能
Bar
Foo
程序无法正常运行
答案是 A foobar 这道题是考线程的调用情况,线程的启动方式只能通过start这种方式启动才能真正的实现多线程的效果,如果是手动调用run方法和普通方法调用没有区别,所以这个还是按照顺序执行首先执行run方法之后,执行输出语句所以最终得到结果foobar.
调用start()后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可动行状态。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体。
1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;
2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码, 这样就没有达到写线程的目的。
58关于以下application,说法正确是什么(B)
public class Test { static int x=10; static {x+=5; } public static void main(String[] args) //4 { System.out.println("x="+x); } static{x/=3; }; }//9

4行与9行不能通过编译,因为缺少方法名和返回类型
编译通过,执行结果是:x=5
编译通过,执行结果是:x=3
9行不能通过编译,因为只能有一个静态初始化器
解释
class A{ static { System.out.println("父类静态代码块"); } public A(){ System.out.println("父类构造方法"); } { System.out.println("父类初始化块"); } } public class B extends A{ static{ System.out.println("子类静态代码块"); } public B(){ System.out.println("子类构造方法"); } { System.out.println("子类初始化块"); } public static void main(String[] args){ new B(); } }

父类静态代码块–>子类静态代码块–>父类普通代码块–>父类构造方法–>子类代码块–>子类构造方法;
首先明确一下执行顺序,静态代码块先于主方法执行,静态代码块之间遵从代码顺序执行。
所以:先初始化静态变量x=10;//x=10
执行第一个静态代码块,x=x+5; //x=15
执行第二静态代码块 x=x/3; //x=5
执行主方法: 输出x=5
拓展一下,在类中定义的{}之间被称为构造块,构造块相对于构造方法先执行,构造块之间按照代码编译顺序执行
此外还有普通代码块,存在于方法之中。
这道题主要考察类加载时候的初始化问题,执行这个类的 main方法,会导致类进行加载,而类加载的属性如下
1、虚拟机在首次加载Java类时,会对静态初始化块、静态成员变量、静态方法进行一次初始化。我们不要去纠结这里的顺序,一般来说我们只需要知道,静态方法一般在最后。
2、只有在调用new方法时才会创建类的实例
3、类实例创建过程:按照父子继承关系进行初始化,首先执行父类的初始化块部分,然后是父类的构造方法;再执行本类继承的子类的初始化块,最后是子类的构造方法
4、类实例销毁时候,首先销毁子类部分,再销毁父类部分
59 以下代码输出结果为(B)
String str = ""; System.out.print(str.split(",").length);

0
1
出现异常
/*** String split 这个方法默认返回一个数组,* 如果没有找到分隔符,* 会把整个字符串当成一个长度为1的字符串数组* 返回到结果, 所以此处结果就是1*/ private static void testSpringSpilte(){ String str = "12,3"; String str2 = "123"; System.out.print(str.split(",").length); System.out.print(str2.split(",").length); } } 结果21

60 下面为true的是(G)
Integer i = 42; Long l = 42l; Double d = 42.0;

(i == l) (i == d) (l == d) i.equals(d) d.equals(l) i.equals(l) l.equals(42L)

解释
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

【牛客刷题笔记--(java基础51-100)】4、基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较。
int i=1; int j = 2; Integer c=3; System.out.println(c.equals(i+j)); //true

多个else if块之间的顺序可以改变,改变之后可能对程序的执行结果有影响
多个else if块之间的顺序可以改变,改变后程序编译可以通过
61 Java1.8版本之前的前提,Java特性中,abstract class和interface有什么区别(ABD)
抽象类可以有构造方法,接口中不能有构造方法
抽象类中可以有普通成员变量,接口中没有普通成员变量
抽象类中不可以包含静态方法,接口中可以包含静态方法=
一个类可以实现多个接口,但只能继承一个抽象类。
接口和抽象类的区别:
1.接口的方法默认为public abstract ,接口中的变量默认为public static final,在java8之前所有的方法不能有实现
抽象类中可以有非抽象方法
2.一个类可以实现多个接口,但只能继承一个抽象类
3.一个类实现接口,要实现该接口的所有抽象方法。
4.接口不能被实例化,但可以声明,但是必须引用一个实现该接口的对象。
抽象类可以有构造方法,但是不能被直接通过new进行实例化。但可以通过子类继承,实例化子类的时候抽象类也会被实例化。
这其实用到了多态,向上转型。父类引用指向子类对象。
5.从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
接口中的成员变量被隐式的声明为public static final
jdk1.8后接口中可以有静态方法而且存在方法体
62 ArrayLists和LinkedList的区别,下述说法正确的有?(ABCD)
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间。
解释
A. ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 //正确,这里的所谓动态数组并不是那个“ 有多少元素就申请多少空间 ”的意思,通过查看源码,可以发现,这个动态数组是这样实现的,如果没指定数组大小,则申请默认大小为10的数组,当元素个数增加,数组无法存储时,系统会另个申请一个长度为当前长度1.5倍的数组,然后,把之前的数据拷贝到新建的数组。
B. 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。//正确,ArrayList是数组,所以,直接定位到相应位置取元素,LinkedLIst是链表,所以需要从前往后遍历。
C. 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。//正确,ArrayList的新增和删除就是数组的新增和删除,LinkedList与链表一致。
D. ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间。//正确,因为ArrayList空间的增长率为1.5倍,所以,最后很可能留下一部分空间是没有用到的,因此,会造成浪费的情况。对于LInkedList的话,由于每个节点都需要额外的指针,所以,你懂的。
63 Java程序的种类有(BCD )
类(Class)
Applet
Application
Servlet
解释:
Java程序的种类有:
(a)内嵌于Web文件中,由浏览器来观看的_Applet
(b)可独立运行的 Application
(c)服务器端的 Servlets
Application
―Java应用程序”是可以独立运行的Java程序。
由Java解释器控制执行。
Applet
―Java小程序”不能独立运行(嵌入到Web页中)。
由Java兼容浏览器控制执行。
Serverlets
是Java技术对CGI 编程的解决方案。
是运行于Web server上的、作为来自于Web browser 或其他HTTP client端的请求和在server上的数据库及其他应用程序之间的中间层程序。
Serverlets的工作是:
读入用户发来的数据(通常在web页的form中)
找出隐含在HTTP请求中的其他请求信息(如浏览器功能细节、请求端主机名等。
产生结果(调用其他程序、访问数据库、直接计算)
格式化结果(网页)
设置HTTP response参数(如告诉浏览器返回文档格式)
将文档返回给客户端。
64 给定代码: 第三行将输出什么?
public class SwitchTest{//1 public static void main(String[] args) {//2 System.out.println("value="https://www.it610.com/article/+switchit(4)); //3 }//4 public static int switchit(int x) { int j=1; switch (x) { case 1:j++; case 2:j++; case 3:j++; case 4:j++; case 5:j++; default:j++; } return j+x; } }

答案: 8
解释:没有break,从case 4开始一直执行到最后,j自加3次变成了4,结果返回8
不加break的话,switch会从第一次进入case语句的地方,一直向下执行完。
65 以下哪个不能用来处理线程安全(D)
synchronized关键字
volatile关键字
Lock类
transient关键字
synchrozied关键字称作同步,主要用来给方法、代码块加锁,被加锁的代码段,同一时间内多线程同时访问同一对象的加锁方法/代码块时,只能有一个线程执行能执行方法/代码块中的代码,其余线程必须等待当前线程执行完以后才执行该方法/代码块。
volatile关键字1.保证了不同线程对该变量操作的内存可见性.(当一个线程修改了变量,其他使用此变量的线程可以立即知道这一修改)。2.禁止了指令重排序.
Lock接口提供了与synchronized关键字类似的同步功能,但需要在使用时手动获取锁和释放锁。
transient关键字 简单地说,就是让某些被修饰的成员属性变量不被序列化。
transient,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。当一个变量不希望被持久化的时候,比如说一些账号密码,就可以用transient关键字来表示该变量不参与序列化过程。
66 String s = new String(“xyz”); 创建了几个StringObject?(A)
两个或一个都有可能
两个
一个
三个
解释:
如果常量池中存在“xyz”就只会创建一个对象,如果没有就会创建两个! ==
1.String对象的两种创建方式:
第一种方式: String str1 = “aaa”; 是在常量池中获取对象(“aaa” 属于字符串字面量,因此编译时期会在常量池中创建一个字符串对象),
第二种方式: String str2 = new String(“aaa”) ; 一共会创建两个字符串对象一个在堆中,一个在常量池中(前提是常量池中还没有 “aaa” 字符串对象)。
System.out.println(str1
str2); //false
2.String类型的常量池比较特殊。它的主要使用方法有两种:
直接使用双引号声明出来的String对象会直接存储在常量池中。
如果不是用双引号声明的String对象,可以使用 String 提供的 intern 方法。 String.intern() 是一个 Native 方法,它的作用是: 如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用; 如果没有,则在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用。
String s1 = new String(“AAA”);
String s2 = s1.intern();
String s3 = “AAA”;
System.out.println(s2); //AAA
System.out.println(s1 == s2); //false,因为一个是堆内存中的String对象一个是常量池中的String对象,
System.out.println(s2 == s3); //true, s2,s3指向常量池中的”AAA“
67 下列流当中,属于处理流的是:(CD)
FilelnputStream
lnputStream
DatalnputStream
BufferedlnputStream
按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。
节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader. 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

JAVA常用的节点流:
文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流。 字符串 StringReader StringWriter 对字符串进行处理的节点流。 数 组 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)。 管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter对管道进行处理的节点流。

常用处理流(关闭处理流使用关闭里面的节点流)
缓冲流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter增加缓冲功能,避免频繁读写硬盘。转换流:InputStreamReader OutputStreamReader 实现字节流和字符流之间的转换。 数据流 DataInputStream DataOutputStream等-提供将基础数据类型写入到文件中,或者读取出来.

流的关闭顺序
一般情况下是:先打开的后关闭,后打开的先关闭 另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b 可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。

此题考察对于java流的理解
节点流是实际工作的流,
处理流(我们叫包装流可能容易理解一点)设计的目的是让对流中数据的操作,转化成我们能更简单明了的看懂的数据(而不是二进制的字节等)的操作,但实际上增加了很多类,是io流变的更复杂
字节流必是一个接点流,字符流就是一个操作流
使用时,必须是有一个结点流,然后才能用操作流来包装结点流,即把结点流当参数传个操作流
节点流:从一个节点读取数据 。处理流:对一个已存在的流进行封装
68 关于Java的一些概念,下面哪些描述是正确的:( BF )
A所有的Java异常和错误的基类都是java.lang.Exception, 包括java.lang.RuntimeException
B通过try … catch … finally语句,finally中的语句部分无论发生什么异常都会得到执行
Cjava中所有的数据都是对象
DJava通过垃圾回收回收不再引用的变量,垃圾回收时对象的finallize方法一定会得到执行
EJava是跨平台的语言,无论通过哪个版本的Java编写的程序都能在所有的Java运行平台中运行
FJava通过synchronized进行访问的同步,synchronized作用非静态成员方法和静态成员方法上同步的目标是不同的
AJava中所有错误和异常的父类是java.lang.Throwable
C基本数据类型不是对象,不能用new的方法获取,但是每个基本数据类型都对应着封装类型,这些封装类型为了解决基本数据类型面向对象用的。
DJava垃圾回收器负责回收无用对象占据的内存资源,但对象没有使用new获取了一块特殊区域,这块特殊区域的回收使用finallize()
EJava跨平台是因为有JVM的存在,Java的三个版本的运行需要各自不同的环境。
A.Error和Exception都是集成Throwable,其中Exception又被IOException和RuntimeException继承/n B.finally语句是无论发生什么异常都会执行的,并且如果try、catch中有return语句,且finally中也有return语句,则finally会覆盖前面的return。值得注意的是,如果try catch中有System.exit(0)的话,就会提前退出 C.java中有基本数据类型,如int,boolean,他们的包装对象是Integer和Boolean,所以不是万物皆对象 D.首先,垃圾回收的优先级相当低。另外,即使垃圾回收器工作,finalize()也不一定得到执行,这是由于程序中的其他线程的优先级远远高于执行finalize()函数线程的优先级。或者说,如果是等待清理队列中如果又被调用,则不会执行finallize()。所以说:Java通过垃圾回收回收不再引用的变量,垃圾回收时对象的finallize()不一定会得到执行。 E.java是跨平台的语言,这个主要是由于有针对不同平台的JVM,而JVM可以无差别的执行字节码(.class文件).但是,平台无关并不意味着版本无关,对于高版本编译器编写的java程序可能无法在低版本的java平台中运行。 F.Synchroized修饰非静态方法,是对调用该方法的对象加锁,Synchroized修饰静态方法,是对类加锁(因为类会调用它,)
69 Which is not Java primitive types?(B)
short
Boolean
byte
float
Java数据类型分为两大类:基本数据类型和引用数据类型(抽象数据类型)
基本数据类型(8种 ):
整型:
byte 1字节 8位(0000 0000)
short 2字节
int 4字节
long 8字节
浮点型:
float 4字节
double 8字节
字符型:
char 2字节
布尔型:
boolean 长度有争议(true,false)
基本数据类型对应的包装类型首字符大写,除过int 和 char
int----->Integer
char---->Character
引用数据类型:(内存中的地址)
类,接口,数组
70 以下多线程对int型变量x的操作,哪几个不需要进行同步( )
x=y;
x++;
++x;
x=1;
A.由于y的值不确定,所以要加锁;
B,C 两个在多线程情况下是必须要加锁的,因为他们是先被读入寄存器,然后再进行+1操作,如果没有加锁,那么可能会出现数据异常;
D 原子操作,所以不需要加锁
原子性:指该操作不能再继续划分为更小的操作。
Java中的原子操作包括:
1、除long和double之外的基本类型的赋值操作
2、所有引用reference的赋值操作
3、java.concurrent.Atomic.* 包中所有类的一切操作
原子性:指该操作不能再继续划分为更小的操作。
Java中的原子操作包括:
1、除long和double之外的基本类型的赋值操作
2、所有引用reference的赋值操作
3、java.concurrent.Atomic.* 包中所有类的一切操作
要进行读写两项操作就需要同步,d选项只需要将1的值赋给x,只进行了写操作,所以不需要同步
71 下面代码的运行结果是(C)
代码编程成功,并输出”s=”
代码编译成功,并输出”s=null”
由于String s没有初始化,代码不能编译通过。
代码编译成功,但捕获到NullPointException异常
成员变量有初始值,而局部变量没有初始值得。本体中的s定义在方法中所以为局部变量-没有初始值。变量没有初始值就使用了,编译通不过
类中实例变量可以不用初始化,使用相应类型的默认值即可;方法中的定义的局部变量必须初始化,否则编译不通过。
72 以下哪个区域不属于新生代?
eden区
from区
元数据区
to区
ava 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大致为:
从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。
本人使用的是 JDK1.6,以下涉及的 JVM 默认值均以该版本为准。
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。
老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
默认的,Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。
因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。
73 关于 Socket 通信编程,以下描述错误的是:( D)
服务器端通过new ServerSocket()创建TCP连接对象
服务器端通过TCP连接对象调用accept()方法创建通信的Socket对象
客户端通过new Socket()方法创建通信的Socket对象
客户端通过new ServerSocket()创建TCP连接对象
解释
Socket套接字
就是源Ip地址,目标IP地址,源端口号和目标端口号的组合
服务器端:ServerSocket提供的实例
ServerSocket server= new ServerSocket(端口号)
客户端:Socket提供的实例
Socket soc=new Socket(ip地址,端口号)
74 请问输出的结果是(false):
class A{ public A(String str){ } } public class Test{ public static void main(String[] args) { A classa=new A("he"); A classb=new A("he"); System.out.println(classa==classb); } }

答案为 false 因为== 表示的是否指向的是同一个内存。
System.out.println(classa.equals(classb)); 如果这这样输出 答案也是错误的 因为子类没有覆盖Object
的equals()方法,而默认调用==的这个方法 判断两个对象是否相等需要覆盖equals()方法和hashcaode()方法
object类――众类鼻祖 1.取得对象信息:toString():对象输出时,会默认调用Object类的toString()方法,将对象信息变为字符串返回。 2.对象相等判断方法:equals():两个对象进行比较时,实际上是比较两个对象的地址值(从程序看出两个对象内容完全相等,但是结果是不相等的,这是因为classa与classb的内容分别在不同的内存空间指向了不同的内存地址)。所以要对equals()进行覆写,判断equals()方法里面的Object类对象是否与调用equals()的类是同一个类的实例(用instanceof判断),如果是,则进行向下转型,然后再调用String类中的equals方法对属性进行比较。 3.对象签名:hashCode():Object类有两种方法来推断对象的标识:equals()和hashCode()。如果根据equals()方法判断两个对象是相等的,那么对这两个对象中的每一个调用hashCode()方法都必然生成相同的整数结果。但是反过来,如果两个hashCode()返回的结果相等,两个对象的equals()方法却不一定相等。在默认情况下equals()方法用来比较两个对象的地址值,而原始的hashCode()方法用来返回其所在对象的物理地址(ps:对于非字符串变量而言,equals和==比较的是地址,对于字符串变量而言equals()比较的是内容 ,两个=比较地址)
这题不管是两个=还是equals输出结果都为false因为equals没有被重写时默认调用两个=进行比较。
75 下列说法正确的有(A)
能被java.exe成功运行的java class文件必须有main()方法
J2SDK就是Java API
Appletviewer.exe可利用jar选项运行.jar文件
能被Appletviewer成功运行的java class文件必须有main()方法
B、C、D都错
A:正确main方法是入口
B:J2SDK当然不仅仅包含java API
C:jar选项是java.exe 的选项
D:Appletviewer是运行applet的, applet 不用main方法,继承applet类即可。
76 下列关于异常处理的描述中,错误的是(D)。
程序运行时异常由Java虚拟机自动进行处理
使用try-catch-finally语句捕获异常
可使用throw语句抛出异常
捕获到的异常只能在当前方法中处理,不能在其他方法中处理
解释
编译时异常必须显示处理,运行时异常交给虚拟机。
运行时异常可以不处理。当出现这样的异常时,总是由虚拟机接管。比如我们从来没有人去处理过Null Pointer Exception异常,它就是运行时异常,并且这种异常还是最常见的异常之一。出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,整个程序也就退出了。运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往不对它处理罢了。也就是说,如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。
捕获到的异常不仅可以在当前方法中处理,还可以将异常抛给调用它的上一级方法来处理。
当一个异常出现时,单靠某个方法无法完全处理该异常,必须由几个方法协作才可以处理,这个时候同时使用catch和throw语句,捕获异常后,只对异常进行部分处理,还有些处理需要在该方法的调用者中才能完成,所以应该再次抛出异常,让该方法的调用者也能捕获到异常
76 对于同一类中的两个方法 , 在判断它们是不是重载方法时 , 肯定不考虑(C)
参数个数
参数类型
返回值类型
参数顺序
方法重载的定义:同一个类或与他的派生类中,方法名相同,而参数列表不同的方法。其中参数列表不同指的是参数的类型,数量,类型的顺序这三种至少有一种不同。
方法重载与下列无关:
与返回值类型无关;与访问修饰符无关
构造方法也可以重载
方法的重写:
方法的重写的定义:在继承关系的子类中,定义一个与父类相同的方法
判断是否重写的方式:在方法之前加上@ Overri de
方法重写的特点:
在继承关系的子类中重写父类的方法
重写的方法必须方法名相同,参数列表也相同
重写的方法的返回值类型应该与父类中被重写方法的返回值类型相同或是他的子类类型
重写的方法的访问权限应该与父类中被重写方法的访问权限相同或高于它的访问权限
重写的方法不能抛出比父类更加宽泛的异常
方法重写的注意事项:
构造方法不能被重写,不要问为什么?因为构造方法名必须和类名相同(因为重写的方法没有返回值或者void不符合java语法规定,因为重写要有返回值类型,而构造方法没有返回值)
private修饰的成员方法不能被重写
static修饰的方法不能被重写
final修饰的方法不能被重写
当子类重写了父类中的方法后,子类对象调用该方法时调用的是子类重写后的方法
重载:类中可以创建多个方法,它们具有相同的名字,但具 有不同的参数和不同的定义。调用方法时通过传递 给它们的不同参数个数和参数类型 给它们的不同参数个数和参数类型 给它们的不同参数个数和参数类型 来决定具体使用哪个方法 , 这就是多态性。
重写 Overriding 是父类与子类之间多态性的一种表现, 在子类中定义某方法与其父类有相同的名称和参数。
重载 Overloading 是一个类中多态性 的一种表现。
重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同 也可以不相同。 无法以 返回型别 作为重载函数的区分标准。而且编译的时候只有返回值不同,会报错。及使不报错,运行时无法区分调用哪个方法
77 以下J2EE中常用的名词解释错误的是?(B)
A :EJB容器:Enterprise java bean 容器
B:JNDI:JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。
C:JMS:JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。
D:JAF:JAVA安全认证框架。提供一些安全控制方面的框架。
JNDI:(Java Naming & Directory Interface)JAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。
JTA:(Java Transaction API)JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。
RMI/IIOP:(Remote Method Invocation /internet对象请求中介协议)他们主要用于通过远程调用服务。例如,远程有一台计算机上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMI是JAVA特有的。RMI-IIOP出现以前,只有RMI和CORBA两种选择来进行分布式程序设计。RMI-IIOP综合了RMI和CORBA的优点,克服了他们的缺点,使得程序员能更方便的编写分布式程序设计,实现分布式计算。首先,RMI-IIOP综合了RMI的简单性和CORBA的多语言性(兼容性),其次RMI-IIOP克服了RMI只能用于Java的缺点和CORBA的复杂性(可以不用掌握IDL)。
78 ArrayList list = new ArrayList(20); 中的list扩充几次(A)
0
1
2
3
Arraylist默认数组大小是10,扩容后的大小是扩容前的1.5倍,最大值小于Integer 的最大值减8,如果新创建的集合有带初始值,默认就是传入的大小,也就不会扩容
79 下列程序的运行结果(A)
public void getCustomerInfo() { try { // do something that may cause an Exception } catch (java.io.FileNotFoundException ex) { System.out.print("FileNotFoundException!"); } catch (java.io.IOException ex) { System.out.print("IOException!"); } catch (java.lang.Exception ex) { System.out.print("Exception!"); } }

IOException! IOException!Exception! FileNotFoundException!IOException! FileNotFoundException!IOException!Exception!

try-catch-finally 规则( 异常处理语句的语法规则 )
  1. 必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
  2. 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
  3. catch 块与相应的异常类的类型相关。
  4. 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或 其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
  5. 可嵌套 try-catch-finally 结构。
  6. 在 try-catch-finally 结构中,可重新抛出异常。
  7. 除了下列情况,总将执行 finally 做为结束: JVM 过早终止(调用 System.exit(int));在 finally 块中抛出一个未处理的异常;计算机断电、失火、或遭遇病毒攻击
    由此可以看出,catch只会匹配一个,因为只要匹配了一个,虚拟机就会使整个语句退出
题目说抛出一个异常,但是没说具体是什么异常,那么就要分情况了:
1.如果抛出一个FileNotFoundException(或其子类),那么最终结果就打印FileNotFoundException
2.如果抛出一个IOException,或者IOException的子类(不包含FileNotFoundException及其子类),那么最终结果就打印IOException
3.如果抛出一个Exception(不包含IOException及其子类),那么最终结果就打印Exception.
以上,所以3个皆有可能.但是,不管是哪一种情况,只会输出其中之一。
从答案上来看,B,C,D的输出情况是不存在的。因此选A
代码块中的do something that may cause an Exception说明程序运行时只会抛出一个异常, 但没有 指明
是什么异常,三种异常均有可能。对于某个异常,只会被捕获一次, 因而只有A是可能的答案, 另外三个
选 项都 捕获了多个异常,与题意不符。
80下面关于volatile的功能说法正确的是哪个(BC)
原子性
有序性
可见性
持久性
==synchronized保证三大性,原子性,有序性,可见性,volatile保证有序性,可见性,不能保证原子性 ==
关于volatile:有序性,可见性,
volatile用与修饰实例变量和类变量,是一种维护线程安全的手段,作用是实现共享资源的可见性
可见性的意思:
进程中的内存分为工作内存(线程内存)和主内存,普通变量的读写依赖于当前工作内存,直到线程结束,才会把值更新到主内存,
当有多线程存在时,就无法保证数据的真实性(可见性),其他线程读到的数据可能旧的.
volatile修饰的变量每次获取的值都是从主内存中直接读的,写完之后也会直接更新到主内存,实现方式以机器指令(硬编码)的方式实现
jkd之后的版本在设计线程安全上都是基于volition和显示锁的方式,很少有用同步块和同步方法的方式,因为同步块方法的来讲,线程以串行的方式经过,效率太低.容易阻塞,而且保持原子性,只要线程进去就无法被打断,而volatile不会阻塞.不保证原子性.
有序性的意思:
jvm和处理器在编译Java代码的时候,出于性能考虑,会对原有的代码进行重排序,(也就是指令重排)我们写好的代码都有顺序,在我们执行的时候由JVM内存模型里的程序计数器标记的,保证线程安全的时候,一般都会禁止指令重排即保证有序性.说是并发环境下指令重排会有很多问题.
但是volatile和synchronized的有序是不同的:
volatile关键字禁止JVM编译器已及处理器对其进行重排序,
synchronized保证顺序性是串行化的结果,但同步块里的语句是会发生指令从排。
深入volatile关键字的介绍
1)被volatile关键字修饰的实例变量或者类变量具备两层语义:
保证了不同线程之间对共享变量的可见性, 禁止对volatile变量进行重排序。

2)volatile和synchronized区别
使用上区别: volatile关键字只能用来修饰实例变量或者类变量,不能修饰方法已及方法参数和局部变量和常量。 synchronized关键字不能用来修饰变量,只能用于修饰方法和语句块。 volatile修饰的变量可以为空,同步块的monitor不能为空。 对原子性的保证 volatile无法保证原子性 synchronizde能够保证。因为无法被中途打断。 对可见性的保证 都可以实现共享资源的可见性,但是实现的机制不同,synchronized借助于JVM指令monitor enter 和monitor exit ,通过排他的机制使线程串行通过同步块,在monitor退出后所共享的内存会被刷新到主内存中。volatile使用机器指令(硬编码)的方式,“lock”迫使其他线程工作内存中的数据失效,不得不主内存继续加载。 对有序性的保证 volatile关键字禁止JVM编译器已及处理器对其进行重排序,能够保证有序性。 synchronized保证顺序性是串行化的结果,但同步块里的语句是会发生指令从排。 其他: volatile不会使线程陷入阻塞 synchronized会会使线程进入阻塞。

81 在Java中下面Class的声明哪些是错误的?(ABC)
public abstract final class Test {
abstract void method();
}
public abstract class Test {
abstract final void method();
}
public abstract class Test {
abstract void method() {
}
}
public class Test {
final void method() {
}
}
== A、final修饰的类为终态类,不能被继承,而 抽象类是必须被继承的才有其意义的,因此,final是不能用来修饰抽象类的。==
B、 final修饰的方法为终态方法,不能被重写。而继承抽象类,必须重写其方法。
C、抽象方法是仅声明,并不做实现的方法。
C中定义的抽象方法没有实体时候,大括号必须省略。
1、抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。
2、抽象方法必须由子类来进行重写。
3、只要包含一个抽象方法的类,该类必须要定义成抽象类,不管是否还包含有其他方法。
4、抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
5、abstract不能与final并列修饰同一个类。
6、abstract 不能与private、static、final或native并列修饰同一个方法。
82 编译java程序的命令文件是(B )
java.exe
javac.exe
applet.exe
javac.exe是编译功能javaCompiler
java.exe是执行程序,用于执行编译好的.class文件
javadoc.exe用来制作java文档
jdb.exe是java的调试器
javaprof.exe是剖析工具
83 一个类的构造器不能调用这个类中的其他构造器。(错误 )
this(x),这种形式的调用就ok
this()和super()都是构造器,this()调用本类构造器,super()调用父类构造器
java构造器内,可以通过this(param)调用本类的重载构造器
84 下面关于依赖注入(DI)的说法不正确的是(A)
只有通过Spring才能实现依赖注入(DI)
依赖注入的主要目的是解耦合
常见的依赖注入方式有Setter和构造方法
答:A,依赖注入是一种思想,或者说是一种设计模式,在java中是通过反射机制实现,与具体框架无关。
Spring依赖注入(DI)的三种方式,分别为:
1. 接口注入
2. Setter 方法注入
3. 构造方法注入
85 下面代码运行结果是(C)
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)); } }

catch语句块 和是:43编译异常finally语句块 和是:43和是:43 finally语句块

1.finally{}代码块比return先执行。
2.多个return是按顺序执行的的,多个return执行了一个后,后面的return就不会执行了。
3. 记住一点,不管有不有异常抛出, finally都会在return返回前执行。

以上结论是自己在eclipse中编译测试过的,不正确之处请多多指教
从结果上看,貌似finally 里的语句是在return 之后执行的,其实不然,实际上finally 里的语句是在在return 之前执行的。那么问题来了,既然是在之前执行,那为什么a 的值没有被覆盖了?
实际过程是这样的:当程序执行到try{}语句中的return方法时,它会干这么一件事,将要返回的结果存储到一个临时栈中,然后程序不会立即返回,而是去执行finally{}中的程序, 在执行a = 2时,程序仅仅是覆盖了a的值,但不会去更新临时栈中的那个要返回的值 。执行完之后,就会通知主程序“finally的程序执行完毕,可以请求返回了”,这时,就会将临时栈中的值取出来返回。这下应该清楚了,要返回的值是保存至临时栈中的。
为什么不是先输出:和是 finally块 43的原因。
System.out.println(“和是:”+test.add(9, 34)); 这是进行字符串拼接是一个整体,所以首先是进入add方法中,进去之后先把先不运算result,而是输出finally块。注意:此时finally块输出结果是:finally语句块,这句话首先打印到控制台中。打印完后返回来执行try中的return得到43,所以此时再将结果与"和是:"进行拼接–>输出:和是 43。所以此时控制台又多了一句话:和是 43。加上之前finally先在控制台上的输出,所以结果为:finally语句块 和是 43.
86 以下哪个不属于JVM堆内存中的区域(B)?
survivor区
常量池
eden区
old区
jvm堆分为:新生代(一般是一个Eden区,两个Survivor区),老年代(old区)。
常量池属于 PermGen(方法区)
堆中的内存可以为了新生代和老年代,新生代由可以分为一个Survivor和两个Eden(From,To),默认比例8:1:1。
其实这个题有问题,从JDK7开始,常量池就从方法区中被移了到了堆(Hotspot叫做永久代),JDK8的时候,永久代被元空间代替。但是这个字符串常量池可是一直都在堆中的。
这里先说一下,方法区和永久代只是针对于HotSpot而言,在JDK7之前是一个概念,对于别的虚拟机而言,可没有什么永久代,只有方法区。
为什么HotSpot把永久代取消了呢,主要是因为这块地方的GC机制和堆邦定在一起,但是因为它不是堆,所以每一个GC收集器都需要有很大一部分代码去专门实现这个区域的垃圾,其次,每次一开始为永久代分配内存的时候,因为无法估量对象的大小,所以总是很难分配合适的内存,还容易出现OOM,所以取代成了元空间。元空间的话相当于一个内地内存,所以基本不会出现什么OOM,但是内存泄漏还是有的。
87在java7中,下列哪个说法是正确的:(D)
ConcurrentHashMap使用synchronized关键字保证线程安全
HashMap实现了Collection接口
Arrays.asList方法返回java.util.ArrayList对象
SimpleDateFormat对象是线程不安全的
hashMap在单线程中使用大大提高效率,在多线程的情况下使用hashTable来确保安全。hashTable中使用synchronized关键字来实现安全机制,但是synchronized是对整张hash表进行锁定即让线程独享整张hash表,在安全同时造成了浪费。concurrentHashMap采用分段加锁的机制来确保安全
HashMap实现的是Map接口,Map和Collection是同一级别的
Arrays.asList()
将一个数组转化为一个List对象,这个方***返回一个ArrayList类型的对象, 这个ArrayList类并非java.util.ArrayList类,而是Arrays类的静态内部类!用这个对象对列表进行添加删除更新操作,就会报UnsupportedOperationException异常。
ConcurrentHashMap使用segment来分段和管理锁,segment继承自ReentrantLock,因此ConcurrentHashMap使用ReentrantLock来保证线程安全。
88以下哪个类包含方法flush()?(B)
InputStream
OutputStream
A 和B 选项都包含
A 和B 选项都不包含
flush()函数强制将缓冲区中的字符流、字节流等输出,目的是如果输出流输出到缓冲区完成后,缓冲区并没有填满,那么缓冲区将会一直等待被填满。所以在关闭输出流之前要调用flush()。
89 以下代码执行的结果显示是多少(B)?
牛客刷题笔记--(java基础51-100)
文章图片

505000
0
运行时错误
5050
count = count++ 原理是 temp = count; count = count+1 ; count = temp; 因此count始终是0 这仅限于java 与c是不一样的
count = count ++; 这个先将count这个值0暂存起来,然后count自加1变成1,最后将暂存的值赋值给count,count最终的值为0
java public class Demo { public static void main(String[] args) { int count = 0; int num = 0; for (int i = 0; i <= 100; i++){ num = num + i; count = count++; } System.out.println("num *count = " + (num * count)); } }

count= 0 num= 5050 num *count = 0

java public class Demo { public static void main(String[] args) { int count = 0; int num = 0; for (int i = 0; i <= 100; i++){ num = num + i; count = count+1; } System.out.println("count= " + count ); System.out.println("num= " + num ); System.out.println("num *count = " + (num * count)); } }

count= 101 num= 5050 num *count = 510050

c++
#include.h> #include using namespace std; class Demo { public: void main2() { int count = 0; int num = 0; for (int i = 0; i <= 100; i++) { num = num + i; count = count++; } cout << "count=" << count<

count=101 num=5050 num *count = 510050

90 Given the following code: import EnclosingOne.InsideOne Which statement at line 11 constructs an instance of the inner class?(AD)
1.class Enclosingone 2.{ 3.public class InsideOne {} 4. 5.} 6.public class inertest 7.{ 8.public static void main(string[]args) 9.{ 10.EnclosingOne eo = new EnclosingOne(); 11.//insert code here 12.} 13. 14.}

InsideOne ei=eo.new InsideOne(); eo.InsideOne ei=eo.new InsideOne(); InsideOne ei=EnclosingOne.new InsideOne(); EnclosingOne.InsideOne ei=eo.new InsideOne();

内部类其实和类的属性没什么区别,只是在声明的时候必须是Outer.Inner a,就像int a 一样,至于静态内部类和非静态内部类new的时候有点区别,Outer.Inner a=new Outer().new Inner()(非静态,先有Outer对象才能有属性) Outer.Inner a=new Outer.Inner()要把Outer.Inner看成一部分,就像类变量一样
声明非静态内部类对象的方法: 外部类名.内部类名 对象名=new 外部类名().new 内部类名();
(注意:此时等号右边需要创建外部类对象,所以有 new 外部类名().new 内部类名())
2.声明静态内部类对象的方法: 外部类名.内部类名 对象名=new 外部类.内部类名();
(注意:此时等号右边不需要创建外部类对象,所以有 new 外部类.内部类名()即可)
91 如果一个接口Cup有个方法use(),有个类SmallCup实现接口Cup,则在类SmallCup中正确的是? (C )
void use() { …}
protected void use() { …}
public void use() { …}
以上语句都可以用在类SmallCup中
解释:
既然是实现接口,就要实现接口的所以方法,相当于重写方法,方法的重写需要满足三同一大一小(方法名、返回值类型、形参相同;访问权限>=重写前;抛出异常<=重写前)
接口,比抽象类还要抽象的类。
接口中每一个方法也是隐式抽象的,接口中的方***被隐式的指定为 public abstract (只能是 public abstract,其他修饰符都会报错)。 接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量(并且只能是 public,用 private 修饰会报编译错误。) 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

注:
接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
接口中的方法都是公有的。public
92 下列代码的输出结果是_____ (B)
boolean b=true?false:true==true?false:true; System.out.println(b);

true
false
null
空字符串
解释:== 优先级高于 三目运算
boolean b=true?false:truetrue?false:true;
true?false:(true
true)?false:true;
true?false:((true==true)?false:true);
false
牛客刷题笔记--(java基础51-100)
文章图片
93 事务隔离级别是由谁实现的?(C)
Java应用程序
Hibernate
数据库系统
JDBC驱动程序
解释
A,我们写java程序的时候只是设定事物的隔离级别,而不是去实现它
B,Hibernate是一个java的数据持久化框架,方便数据库的访问
C,事物隔离级别由数据库系统实现,是数据库系统本身的一个功能
D,JDBC是java database connector,也就是java访问数据库的驱动
94 有以下类定义: 运行后: (B)
abstract class Animal{ abstract void say(); } public class Cat extends Animal{ public Cat(){ System.out.printf("I am a cat"); } public static void main(String[] args) { Cat cat=new Cat(); } }

I am a catAnimal能编译,Cat不能编译Animal不能编译,Cat能编译编译能通过,但是没有输出结果

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点区别:
1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
2)抽象类不能用来创建对象;
3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。
在其他方面,抽象类和普通的类并没有区别。
基类是抽象类,子类继承父类,但是没有实现基类的抽象方法,那么子类也是抽象类。抽象类不能创建对象,所以在主函数中创建对象编译不会通过。
95 现有如下代码段:假设n>=0,则其时间复杂度应为( A )
x = 2; while(x

O(log2(n))
O(nlog2(n))
O(n)
O(n^2)
牛客刷题笔记--(java基础51-100)
文章图片
1、时间复杂度
(1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
(2)时间复杂度 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
算法的时间复杂度和空间复杂度-总结
96 在java7中,下列不能做switch()的参数类型是?(D)
int型
枚举类型
字符串
浮点型
switch语句后的控制表达式只能是short、char、int、long整数类型和枚举类型,不能是float,double和boolean类型。String类型是java7开始支持。
switch支持 int及以下(char, short, byte),String, Enum
在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long、float、double类型不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。
注意:String类型是Java7开始支持的。
97 阅读如下代码。 请问,对语句行 test.hello(). 描述正确的有(A)
package NowCoder; class Test { public static void hello() { System.out.println("hello"); } } public class MyApplication { public static void main(String[] args) { // TODO Auto-generated method stub Test test=null; test.hello(); } }

能编译通过,并正确运行
因为使用了未初始化的变量,所以不能编译通过
以错误的方式访问了静态方法
能编译通过,但因变量为null,不能正常运行
解释
当程序执行Test tset时:jvm发现还没有加载过一个称为”Test”的类,它就开始查找并加载类文件”Test.class”。它从类文件中抽取类型信息并放在了方法区中,jvm于是以一个直接指向方法区java类的指针替换了’test’符号引用,以后就可以用这个指针快速的找到Test类了。所以这也是为什么可以直接test.任何静态的东西
静态方法属于静态绑定,编译器根据引用类型所属的静态类型为它绑定其对应的方法。此语句会翻译成invokestatic,该指令的调用中不会涉及this,所以不会依赖对象! 还有引用类型=null,其实就是指该引用在堆中没有对应的对象,但是编译的时候还是能根据声明找到其所属的静态类型。
因为Test类的hello方法是静态的,所以是属于类的,当实例化该类的时候,静态会被优先加载而且只加载一次,所以不受实例化new Test(); 影响,只要是使用到了Test类,都会加载静态hello方法!
另外,在其他类的静态方法中也是可以调用公开的静态方法,此题hello方法是使用public修饰的所以在MyApplication中调用hello也是可以的。
总结:即使Test test=null; 这里也会加载静态方法,所以test数据中包含Test类的初始化数据。(静态的,构造的,成员属性)因此test.hello是会调用到hello方法的。
98 在Java中,关于HashMap类的描述,以下正确的是 (ACD)
HashMap使用键/值得形式保存数据
HashMap 能够保证其中元素的顺序
HashMap允许将null用作键
HashMap允许将null用作值
牛客刷题笔记--(java基础51-100)
文章图片

HashMap 不按插入顺序排序,按照哈希值排序。所以无序。
但是不增删改键的情况下,输出是按照一定顺序不变的
99 关于Java和C/C++的比较,下列哪个描述是错误的?(CD)
Java不支持指针,C/C++支持
Java程序不需要显式地关心内存释放,而C/C++需要
Java和C++一样,是纯编译型语言,因此它们的class都是在编译时静态联编(static binding)的
Java数组、字符串不可能溢出,C/C++数组、字符串则有可能溢出边界
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(类型不匹配)。
编译型语言和解释性语言:编译型语言在程序执行之前,先会通过编译器对程序执行一个编译的过程,把程序转变成机器语言。运行时就不需要翻译,而直接执行就可以了。最典型的例子就是C语言。
解释型语言就没有这个编译的过程,而是在程序运行的时候,通过解释器对程序逐行作出解释,然后直接运行,最典型的例子是Ruby。但是,随着Java等基于虚拟机的语言的兴起,我们又不能把语言纯粹地分成解释型和编译型这两种,用Java来举例,Java首先是通过编译器编译成字节码文件,然后在运行时通过解释器给解释成机器文件。所以我们说Java是一种先编译后解释的语言。
静态联编是指编译时多态,动态联编是指运行时多态,看网上多指C++。
java字符串可以拼接,这个溢出的限定不好判断,但是数组是一定可以溢出的。
100 HashSet子类依靠()方法区分重复元素。(C)
toString(),equals()
clone(),equals()
hashCode(),equals()
getClass(),clone()
HashSet的底层还是用HashMap来实现的。将Entry的V都变成了同一个Object对象,public static final PRESENT = new Object()。
而HashMap的数据结构是数组+链表+红黑树。
调用K的hashCode方法,然后高低16位进行&运算。得到的hash值,与数组tab[](桶)的长度-1进行&运算,确定插入对象在哪一个桶上。然后调用对象的equals方法,形成链表。当链表长度大于8时,链表转红黑树。
比较对象相等时也是要最好同时重写这两个方法。一直记着hashcode用来找桶,equals用来在桶里找相同那一个。

    推荐阅读