java面试题03
一:一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
可以包含多个类,在一个class中可以有多个类,但是只能有一个public修饰的类,并且这个类名(public class Test)和文件名字(Test.java)必须一致,作为提供外部调用的唯一的开口,否则编辑器就会报错。
二:Switch 能否作用在byte上,能否作用在long上,能否作用在string上?
01.switch(表达式)中的表达式可以为: byte, short , int, char , 以及其对应的包装类, 枚举类(enum) , 以及String(JDK1.7之后支持的)。
02.case后跟的常量值不允许重复。
03.switch(表达式):表达式为整形变量或字符变量。
三:说说final,finally,finalize的区别?
1.final:修饰符(关键字),可以修饰变量,方法和类。
01.final修饰的变量就是常量,只能一次性赋值,不能修改。
02.final修饰的类不能被继承。
03.final修饰的方法不能被重写。
04.final不能与abstract连用。
05.final可以在构造方法中赋值。
2.Finally:用在捕捉异常时候的关键字,和try catch连用,不管有无异常 都会走。
01.try-catch-finally结构中,try是必须要有的,catch和finally语句均可选择,但是两者至少有一个。
02.finally:不管怎样,都要执行。只有一种情况不执行,就是在catch中出现
System.exit(1);中断程序。
03.存在return的try-catch-finally块,当try或者catch里有return时,也要先执行finally,再执行return。
3.Finalize():方法名。
Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
四:Math.round(11.5)和Math.round(-11.5)分别等于多少?
Math.round(11.5):结果为 11
Math.round(-11.5):结果为-11
Math.round(-11.6):结果为-12
Math类的round()方法底层实现为:return (long)floor(a + 0.5d);
01、参数的小数点后第一位<5,运算结果为参数整数部分。
02、参数的小数点后第一位>5,运算结果为参数整数部分绝对值+1,符号(即正负)不变。
03、参数的小数点后第一位=5,正数运算结果为整数部分+1,负数运算结果为整数部分。
总结:大于五全部加,等于五正数加,小于五全不加。
五:说说 string stringBuffer,stringBuilder的区别?
1.String是一个不可变的对象,每次对String类型的字符串进行改变时就相当于生成了一个新的String对象。
其底层为: private final char value[];所以是不可变对象。
2.StringBuffer和StringBuilder都继承了AbstractStringBuilder,而StringBuffer大部分方法都是synchronized,也就是线程安全的,
而StringBuilder就没有,所以,我们查看API可以知道,StringBuilder可以操作StringBuffer,但是StringBuffer不可以操作StringBuilder,这也是线程的原因;
所以,可想而知,StringBuffer的效率肯定没有StringBuilder,因为StringBuffer要维持同步锁,这肯定要消耗部分资源
3.执行效率:StringBuilder>StringBuffer>String,所以,如果这是考虑单线程程序的话,用StringBuilder,如果涉及到多线程的,那只能是StringBuffer。
六:为什么不建议记录日志时使用 System.out.println()?
System.out.println()是在控制台输出信息,控制台的内存空间有限,不能存储所有的日志记录,而且当日志数据量非常大时查找指定的日志难度较大,在控制台输出日志还会增加服务器负担,影响其性能。可以使用log4j。
七:运行时异常和普通异常有什么区别?
理 异常分为两类 runTime exeception 和checked exception
1.前者是运行时异常 ,此类异常不需要我们去catch 虚拟机会主动帮我们 往上抛,知道抛到单线程的main() 或者多线程的 Thread.run() ,之后抛出,程序终止,这类异常常见的有
NullPointerExECEPTION ArrayIndexOutOfBoundExeception等异常,如果出现异常肯定是程序员书写错误,需要排查
2.后者异常,多是由于外部环境引起的异常,如IO SQL 这时候系统会强制我们去catch
八:Thread.Sleep()和object.Wait()有什么区别?
1.Tnread.sleep()是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,此时系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制,但是监控状态依然保持,到时后会自动恢复,调用sleep不会释放对象锁。
2.Object.wait()是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,此时线程不占用任何资源,不增加时间限制,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
九:当一个线程进入一个对象的一个synchronized方法后,其他线程是否可以进入此对象的 其他synciinized方法 和普通方法?
(1)其他方法前是否加了synchronized关键字,如果没加,则能。
(2)如果这个方法内部调用了wait,则可以进入其他synchronized方法。
(3)如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。
(4)如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。
十:如何遍历hashMap?
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "11");
map.put(2, "22");
map.put(3, "33");
map.put(4, "44");
第一种:通过Map.keySet遍历key和value:
for (Integer in : map.keySet()) {
String str = map.get(in);
System.out.println(in + " " + str);
}
第二种:通过Map.entrySet使用iterator遍历key和value:
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
第三种:通过Map.entrySet遍历key和value;
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= "
+ entry.getValue());
}
第四种:.value()方法遍历map的值
System.out.println("第四种:通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
十一:set中的元素不能重复,用什么方法区分是否重复呢?使用==还是用equals?他们有什么区别?
01.Set是Collection容器的一个子接口,它不允许出现重复元素,当然也只允许有一个null对象。
02.使用equals来判断两个元素是否重复。
03.==是用来判断两者是否是同一对象(同一事物),而equals是用来判断是否引用同一个对象。
再看一下Set里面存的是对象,还是对象的引用。根据java的存储机制可知,set里面存放的是对象的引用,所以当两个元素只要满足了equals()时就已经指向同一个对象,
也就出现了重复元素。所以应该用equals()来判断。
十二:写一个方法,计算斐波那契数列(1,1,2,3,5,8,...)第100项的值,方法参数为第N项,返回值为第N项的值(考虑程序运算效率,异常处理)?
第一百项的值:354224848179261915075
public static BigDecimal getNum(Integer n){
boolean flag=true;//声明一个标识符
List<BigDecimal> lists = new ArrayList<BigDecimal>();//声明一个集合存储斐波那契数列的值
try {
for(int i=1;i<=n;i++){
if (i<=2) {//斐波那契数列前两项值
lists.add(new BigDecimal(1));
}else{//大于两项后的值计算
lists.add((lists.get(i-3).add(lists.get(i-2))));
}
}
for (BigDecimal bigDecimal : lists) {//便利斐波那契数列
System.out.println(bigDecimal);
}
} catch (Exception e) {
flag=false;
System.err.print("出错了");
e.printStackTrace();
}
if (flag) {
return lists.get(n-1);//返回第n象的值
}else{
return new BigDecimal(0);
}
十三:谈谈你对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 的首选方法;
十四:java进程间通信的方式有哪些?
(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关 系 进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送 信号给进程本身;Linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
(7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
(8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
十五:CSS规则style=“padding:0 0 3px 3px” 设置的元素内边距分别多少?
01.上内边距:0px
02.右内边距0px
03.下内边距3px
04.左内边距3px
十六:说出http请求的get 和post方式的区别?
01.Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求
02.Get是获取信息,而不是修改信息,类似数据库查询功能一样,数据不会被修改
03.Get请求的参数会跟在url后进行传递,请求的数据会附在URL之后,以?分割URL和传输数据,参数之间以&相连,%XX中的XX为该符号以16进制表示的ASCII,如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密。
04.Get传输的数据有大小限制,因为GET是通过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了,不同的浏览器对URL的长度的限制是不同的。
05.GET请求的数据会被浏览器缓存起来,用户名和密码将明文出现在URL上,其他人可以查到历史浏览记录,数据不太安全。在服务器端,用Request.QueryString来获取Get方式提交来的数据
06.Post请求则作为http消息的实际内容发送给web服务器,数据放置在HTML Header内提交,Post没有限制提交的数据。Post比Get安全,当数据是中文或者不敏感的数据,则用get,因为使用get,参数会显示在地址,对于敏感数据和不是中文字符的数据,则用post
07.POST表示可能修改变服务器上的资源的请求,在服务器端,用Post方式提交的数据只能用Request.Form来获取
十七:Servlet 的forward和redirect的区别?
01.forward:转发是服务器行为,转发的时候浏览器不知道他所请求的具体资源来源,所以url不会变。转发的时候可以共享request里面的数据。
02.redirect:重定向是客户端行为,服务器根据逻辑发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的URL,重定向不能携带参数。
十八:写一段jdbc查询orical数据库的代码?
package com.test.dbtest;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestO_procedure01 {
public static void main(String[] args) {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:Oracle:thin:@localhost:1521:orcl";
PreparedStatement stmt = null;
ResultSet res = null;
Connection conn = null;
CallableStatement proc = null;
String sql = " select t.tid, t.tname,t.tage from teacher t where t.name=upper('AT')";
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, "abc123", "abc123");
stmt = conn.prepareStatement(sql);
res = stmt.executeQuery();
while(res.hasNext())
{
String tid = res.getInt("tid");
String tname = res.getString("tname");
String tage= res.getInt("tage");
System.out.println(tid+" "+tname+" "+taget);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
十九:JDBC中preparameter比statement的好处?
01.极大提高了安全性能,可以防止sql注入
02.代码的可读性和可维护性相比Statement要好.
03.有预编译功能,相同操作批量数据效率较高
因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行
二十:选择自己熟悉的数据库。写出下列SQL语句:
建立表library;
mysql: create table library(
lid INT(6) PRIMARY KEY AUTO_INCREMENT,
lname CHAR(12);
lsum INT(8)
)
oracle:create table library
( lid number(6) not null,
lname varchar2(12) not null,
ldate date,
lusersex varchar2(2)
);
插入多个数据
insert into library (lid,lname,ldate,lusersex) values (1200,’小小’,’女’,to_date(‘2016-08-08’,’yyyy-mm-dd’));
添加主键约束
alter table library constraint pk_library_lid primary key(lid);
添加唯一约束
alter table library add constraint uk_library_lname unique(lname);
添加检查约束
alter table library add constraint ck_library_lusersex check(lusersex in
(‘男’,’女’));
添加外键约束:
alter table library fk_library_lid foreign key(lid) references user (ulid);