java面试题03

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java面试题03相关的知识,希望对你有一定的参考价值。

1、一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
这个是可以的,一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致。

每个编译单元只能有一个public 类。这么做的意思是,每个编译单元只能有一个公开的接口,而这个接口就由其public 类来表示。
你可以根据需要,往这个文件里面添加任意多个提供辅助功能的package 权限的类。但是如果这个编译单元里面有两个或两个以上的public 类的话,程序就不知道从哪里导入了,编译器就会报错。


2、switch能否作用在byte上,能否作用在long上,能否作用在String上?

switch语句中的表达式只能是byte,short,char ,int以及枚举(enum),所以当表达式是byte的时候可以隐含转换为int类型,而long字节比int字节多,不能隐式转化为int类型,所以switch语句可以用在byte上而不可以用在long上,另外由于在JDK7.0中引入了新特性,所以witch语句可以接收一个String类型的值,String可以作用在switch语句上

3、说说final、finally、finalize三者的区别。
1.final:如果一个类被final修饰,意味着该类不能派生出新的子类,不能作为父类被继承。因此一个类不能被声明为abstract,又被声明为final。将变量或方法声明为final。可以保证他们在使用的时候不被改变。其初始化可以在两个地方:一是其定义的地方,也就是在final变量在定义的时候就对其赋值;二是在构造函数中。这两个地方只能选其中的一个,要么在定义的时候给值,要么在构造函数中给值。被声明为final的方法也只能使用,不能重写。

2.finally:在异常处理的时候,提供finally块来执行任何的清除操作。如果抛出一个异常,那么相匹配的catch字句就会执行,然后控制就会进入finally块,前提是有finally块。

3.finalize:finalize是方法名,java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是在垃圾收集器确认一个对象没有被引用时对这个对象调用的。它是在Object类中定义的,因此,所有的类都继承了它。子类覆盖finalize()方法已整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。


4、Math.round(11.5)和Math.round(-11.5)分别等于多少?
Math.round(11.5)的结果是12,Math.round(-11.5)的结果为-11

5、说说String、StringBuffer、StringBuilder的区别。
01、区别

String类型和StringBuffer类型的主要性能区别其实在于String是不可变对象,因此在每次对String类型进行改变的时候其实都等于生成了一个新的String对象,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM的GC就会开始工作,那速度一定会相当慢的。

02、执行速度:

三者在执行速度方面的比较:StringBuilder>StringBuffer>String

03、使用场景:

a、如果要操作少量的数据用String

b、单线程操作字符串缓冲区下操作大量数据 使用StringBuilder

c、多线程操作字符串缓冲区 下 操作大量数据使用 StringBuffer

 


6、为什么不建议记录日志时使用System.out.println()。
我相信很多的Java新手都非常喜欢使用System.out.println()方法来打印日志,不知道你是不是也喜欢这么做。不过在真正的项目开发中,是极度不建议使用System.out.println()方法的!如果你在公司的项目中经常使用这个方法,就很有可能要挨骂了。
为什么System.out.println()方法会这么遭大家唾弃呢?经过我仔细分析之后,发现这个方法除了使用方便一点之外,其他就一无是处了。方便在哪儿呢?在Eclipse中你只需要输入syso,然后按下代码提示键,这个方法就会自动出来了,相信这也是很多Java新手对它钟情的原因。那缺点又在哪儿了呢?这个就太多了,比如日志打印不可控制、打印时间无法确定、不能添加过滤器、日志没有级别区分……
听我说了这些,你可能已经不太想用System.out.println()方法了,那么Log就把上面所说的缺点全部都做好了吗?虽然谈不上全部,但我觉得Log已经做得相当不错了。我现在就来带你看看Log和LogCat配合的强大之处。
首先在LogCat中是可以很轻松地添加过滤器的,你可以在图1.21中看到我们目前所有的过滤器。

 


7、运行时异常和普通异常有什么区别?
Java 提供了两类主要的异常 :runtime exception 和 checked exception 。 checked 异常也就是我们经常遇到的 IO 异常,以及 SQL 异常都是这种异常。 对于这种异常, JAVA 编译器强制要求我们必需对出现的这些异常进行 catch 。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆 catch 块去处理可能的异常。
但是另外一种异常: runtime exception ,也称运行时异常,我们可以不处理。当出现这样的异常时,总是由虚拟机 接管。比如:我们从来没有人去处理过 NullPointerException 异常,它就是运行时异常,并且这种异常还是最常见的异常之一。

 


8、Thread.sleep()和Object.wait()有什么区别?
1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。


2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。


3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
synchronized(x){
x.notify()
//或者wait()
}


4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

 


9、当一个线程进入一个对象的一个synchronized方法后,其他线程是否可以进入此对象的其他synchronized方法和普通方法?
1.其他方法前是否加了synchronized关键字,如果没加,则能。
2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。
3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。

 

10、如何遍历HashMap。
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
map.put("4", "value4");

//第一种:普通使用,二次取值
System.out.println("\n通过Map.keySet遍历key和value:");
for(String key:map.keySet())
{
System.out.println("Key: "+key+" Value: "+map.get(key));
}

//第二种
System.out.println("\n通过Map.entrySet使用iterator遍历key和value: ");
Iterator map1it=map.entrySet().iterator();
while(map1it.hasNext())
{
Map.Entry<String, String> entry=(Entry<String, String>) map1it.next();
System.out.println("Key: "+entry.getKey()+" Value: "+entry.getValue());
}

//第三种:推荐,尤其是容量大时
System.out.println("\n通过Map.entrySet遍历key和value");
for(Map.Entry<String, String> entry: map.entrySet())
{
System.out.println("Key: "+ entry.getKey()+ " Value: "+entry.getValue());
}

//第四种
System.out.println("\n通过Map.values()遍历所有的value,但不能遍历key");
for(String v:map.values())
{
System.out.println("The value is "+v);
}
}

 


11、Set中的元素不能重复,用什么方法来区分是否重复呢?是用==还是用equals?它们有什么区别?
==和equals()的区别
==是判断对象的内存地址,s1==s2,s2的引用的对象跟s1是同一个。
Object类的equals 也是判断对象的内存地址。底层也是用的==。
有一些类复写了equals(),判断的是此对象的具体内容
Set里的元素是不能重复的,元素重复与否是使用equals()方法进行判断的。
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值

 


12、 写一个方法,计算斐波那契数列(1,1,2,3,5,8,...)第100项的值,方法参数为第N项,
第一百项的值为3736710778780434371

方法:
public long shu(int t){
int d =t-3;
long x=2;
long y=1;
for(int i=0;i<d;i++){
long r=x;
x=x+y;
y=r;
}
return x;
}

@Test
public void ku(){
long u= shu(100);
System.out.println(u);
}
}

 

13、谈谈你对java.math.BigDecimal类的认识。

Java中提供了大数字(超过16位有效位)的操作类,即 java.math.BinInteger 类和 java.math.BigDecimal 类,用于高精度计算.
其中 BigInteger 类是针对大整数的处理类,而 BigDecimal 类则是针对大小数的处理类.
BigDecimal 类的实现用到了 BigInteger类,不同的是 BigDecimal 加入了小数的概念.
float和Double只能用来做科学计算或者是工程计算;在商业计算中,对数字精度要求较高,必须使用 BigInteger 类和 BigDecimal 类,它支持任何精度的定点数,可以用它来精确计算货币值.
BigDecimal类创建的是对象,不能使用传统的+、-、*、/等算术运算符直接对其进行数学运算,而必须调用其对应的方法.方法的参数也必须是BigDecimal类型的对象.

构造 BigDecimal 对象常用以下方法:
BigDecimal BigDecimal(double d); //不允许使用
BigDecimal BigDecimal(String s); //常用,推荐使用
static BigDecimal valueOf(double d); //常用,推荐使用


其中,
1. double 参数的构造方法,不允许使用!!!!因为它不能精确的得到相应的值;
2. String 构造方法是完全可预知的: 写入 new BigDecimal("0.1") 将创建一个 BigDecimal,它正好等于预期的0.1; 因此,通常建议优先使用 String 构造方法;
3. 静态方法 valueOf(double val) 内部实现,仍是将 double 类型转为 String 类型; 这通常是将 double(或float)转化为 BigDecimal 的首选方法;

BigDecimal aDouble =new BigDecimal(1.22);
System.out.println("construct with a double value: " + aDouble);
结果: construct with a doublevalue:1.2199999999999999733546474089962430298328399658203125

BigDecimal aString = new BigDecimal("1.22");
System.out.println("construct with a String value: " + aString);
结果: construct with a String value: 1.22

《详情:http://blog.csdn.net/jackiehff/article/details/8582449》

14、Java进程间通信的方式有哪些。
(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
   (2)命名管道(named pipe):命名管道克服了管道没有名字的限制,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
   (3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送 信号给进程本身。
   (4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。
   (5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。
   (6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
   (7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
   (8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。


15、CSS规则style=”padding:0 0 3px 3px”设置的元素内边距分别多少。

上右下左

padding:0px 1px 2px 3px 上为0,右为0,下为3,左为3

16、说出HTTP请求的GET和POST方式的区别。
1、GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。URL的编码格式采用的是ASCII编码,而不是uniclde,即是说所有的非ASCII字符都要编码之后再传输。

POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。上面的item=bandsaw就是实际的传输数据。

因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。

2、传输数据的大小

在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。

对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置

3、安全性
POST的安全性比GET的高。这里的安全是指真正的安全,而不同于上面GET提到的安全方法中的安全,上面提到的安全仅仅是不修改服务器的数据。
比如,在进行登录操作,通过GET请求,用户名和密码都会暴露再URL上,因为登录页面有可能被浏览器缓存以及其他人查看浏览器的历史记录的原因,
此时的用户名和密码就很容易被他人拿到了。除此之外,GET请求提交的数据还可能会造成Cross-site request frogery攻击
17、Servlet的forward和redirect的区别。
重定向:
response.sendRedirect("地址");
a. 页面地址显示最终页面
b. 不可向后传递参数
c. 跳到外部站点

服务器转发:
request.getRequestDispatcher("地址").forward(request, response);
a. 页面地址显示请求页面
b. 可以向后传递参数
c. 不可以跳到外部站点

重定向发出两次请求, 转发只发一次请求
18、写一段JDBC查询oracle数据的代码。
Connection conn = null;
ResultSet rs = null;
//加载驱动
Clas敏感词orName("oracle.jdbc.OracleDriver");
//获得连接
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl",
"scott",
"tiger");
Statement stat = conn.createStatement();
//sql语句
String sql = "SELECT * FROM emp";
//执行语句获得结果集
rs = stat.executeQuery(sql);
//遍历结果集
while(rs.next()){
String name = rs.getString("name");
System.out.println(name);}
//关闭链接
conn.close();

19、JDBC中PreparedStatement相比Statement的好处
一.代码的可读性和可维护性.
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.
都比直接用Statement的代码高很多档次;

二.PreparedStatement尽最大可能提高性能.
每一种数据库都会尽最大努力对预编译语句提供最大的性能优化 .因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,
那么下次调用时只要是相同的预编译语句就不需要编译,
只要将参数直接传入编译过的语句执行代码中( 相当于一个函数,用就是了,不用重写一个来实现 )就会得到执行.

三.最重要的一点是极大地提高了安全性.
使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系
只要全使用预编译语句,你就用不着对传入的数据做任何过虑(因为后面传过来的只作参数用,而不参与编译,
那就不会对含有sql的语句的参数再编译一次,而留下sql拼接的安全漏洞

20、选择自己熟悉的数据库,写出下列SQL语句:
建立表library:
create table library if not exists(

id int(10) not null primary key auto-increment comment "id",
age int(10) not null comment"年龄",
sex varchar(20) default "男" comment "性别",

)charset=utf-8 default engine=Innodb;
















































































































































































以上是关于java面试题03的主要内容,如果未能解决你的问题,请参考以下文章

java面试题03

java面试题03

java面试题03

java面试题03

面试题2020-03-24Java线程池七个参数详解

Java面试题01