您的位置:首页 > 编程语言 > Java开发

JAVA常见问题总结

2015-12-30 16:52 405 查看
一 基本类型

1. 基本类型有哪些,什么叫自动装拆箱操作

答:基本类型有:int long short byte char float double boolean

自动装拆箱操作是系统自动将基本类型转变成对象类型叫装箱操作,对象类型自动转化成基本类型叫拆箱操作

2.Java在存取对象类型数据和基本类型数据的方式有什么不同

答:JVM分配内存的方式有2种,分别为堆和栈,栈的存取速度仅次于CPU,但存储在栈中的数据,并需有确定的生命周期和需要的内存大小,如基本类型数据,对象指针(并非对象的数据),而堆存取速度比栈慢,但存储的数据可以动态改变空间大小,及生命周期也不用在编译期就确定,一般用来存储数组,对象数据

3.运算结构优先级

操作符结合性
[] ()(方法调用)从左到右
!~ ++ -- +(一元运算) -(一元运算符)从右到左
* / %从左到右
+ -从左到右
<< >> >>>从左到右
=< => < > instanceof从左到右
== !==从左到右
&从左到右
^从左到右
|从左到右
&&从左到右
||从左到右
?从右到左
+= -= >>= <<= >>>= /= *= %=从右到左
二 类

1.面向对象有哪些特点

多态性:一个类实例相同方法在不同情形下有不同的表现形式。多态机制可以使具有不同内部结构的对象共享相同的外部接口。

封装:把客观的事物封装成抽象的类,并且类里面的数据和方法只能让自己或可信任的类访问,对于不可信任的类进行信息隐藏。

继承:可以让某个类型对象获得另一个类型对象的属性和方法。它可以使用现有类的所有功能,并且在不需要重写原来类的情况下对功能进行扩展。

面向对象三大基本特征

2.修饰符有哪些,这些修饰符对于修饰属性、方法和类有什么区别?

final:修饰属性时,说明该属性不能被修改,只能在声明处或构造函数中对属性赋值。如果修饰的是方法,则说明该方法不能被覆盖重写。如果修饰的是类,说明该类不能被继承。

static:修饰属性和方法时,说明该属性或方法属于类,也可以用来修饰内部类

public:修饰属性、方法、或类时,可以被如何类访问

private:指定所修饰的方法或属性,只能被该类方法

protected:该属性或方法只能被当前类或子类访问

transient:序列化对象时,忽略该修饰符指定的属性

abstract:可以用来指定抽象方法或抽象类,有抽象方法的类一定是抽象类

3.super和this分别有什么用

super关键字是用来指向父类,构造一个类实例时,会默认调用super()函数,也可以通过super(...)指定特定的父类构造函数,如果一个类覆盖了父类某个方法,也可以通过super来访问被覆盖的方法。

this关键字是用来指定当前对象的引用,当参数名和属性名相同时,可以用this来指定属性,也可以在构造函数中通过this(..)间接调用其它构造函数。

4.抽象类,接口和类有什么区别

接口只能用来申明函数,及带有静态的常量属性,而类和抽象类可以定义正常的属性及函数实现,但抽象类通过stract关键字,也能申明函数。

接口是多继承和类、抽象类是单继承。既是接口可以同时有多个父接口,而抽象类和类只能有一个父类。

详细的抽象类和接口区别及使用

5.匿名类和内部类在什么情况下使用?

匿名类适用于只想使用一次实现接口或覆盖类中方法的对象情况。如:通过Runnable接口实现线程

内部类由于内部类能访问外部类私有变量或方法,但外部类不能访问内部类的私有变量或方法,因此,可以通过内部类的方式,屏蔽一些重要信息及处理细节,避免外部类错误的调用。如:Map接口中的Entry类

三 线程

1.实现线程的方式有多少种,分别适用于什么情况

继承Thread类重写run方法:线程业务处理不是派生类情况下,可以使用这种方式。

实现Runnable接口:适用于线程业务是派生类的情况,因为,在java中对象是单一继承。

通过Executor线程池方式:适用于控制线程数量或频繁使用线程的情况下

2.实现同步的方式有几种,它们有什么区别

主要有2种方式分别为synchronized和Lock接口,synchronized能在程序出现异常或执行完同步块后自动释放锁,不支持读写锁及中断锁,同步块只能让一个对象获得,而Lock能够灵活的控制和使用锁,但必须手动释放锁,否则很容易导致死锁产生,Lock支持读写锁机制并且可以中断锁,在性能和灵活性上比synchronized好。

3.线程中wait() sleep() yield()的区别

wait()属于Object类中的方法,它能释放锁,并挂起线程,让出cup资源,直到notify()或notifyAll()唤醒才能使用

sleep()也能挂起线程,让出cup资源一定时间,但不会释放已拥有的锁

yield()和sleep()一样,但是如果cup处于空闲状况下,会立刻重新获取Cup资源,而不是等待到指定时间

注意:sleep()和yield()函数并不是时间一到即可获取到资源,系统只是将其加入到cup资源请求队列中,具体何时获得,是不可预知的

4.Object中的wait(),notify()和notifyAll()与Condition类的区别

它们都是用来解决消费者-生产者问题,Condition的灵活性和性能比Object的高,但Condition需要依赖Lock接口,Condition能为消费者和生产者设置条件,可以通过Condition唤醒该访问内的线程,而Object切办不到,如当有生产者生产完产品时,需要唤醒一个消费者线程,可以通过消费者的Condition对象直接就能唤醒一个消费者线程,但Object不行,它通过notify()唤醒的线程可能是生产者的,也可能是消费者。

四 集合和数组

1.集合接口有哪些,及它们的实现类,这些实现类中哪些是线程安全的



其中Vector,HashTable和Stack是线程安全,其他可以通过Collections中的静态方法转化成线程安全集合。

2.Collection和Collections有什么区别

Collection接口是所有集合的父类,否则定义集合常规操作,而Collections是工具类,提供一些常用于,添加,排序,查找,同步化操作静态函数。

3.Collections和Arrays有什么区别

Collections和Arrays都是工具类,Collections针对集合,而Arrays针对数组。

4.对集合使用,有什么优化建议

1. ArrayList适用于对元素的随机访问,但不适用于经常对集合进行增删修改操作,尽量在初始化ArrayList是给出容量的大小。

2. LinkedList和ArrayList刚好相反,它适合用于进行增删修改操作,当随机查找性能比ArrayList低,因为,ArrayList是通过数组的方式实现,而LinkedList是使用链表的方式

3. 需要确保集合中元素不相同,可以使用Set集合的实现类,在确保元素不重复的前提下需要对集合中元素排序,可以使用TreeSet集合

4. 使用Map集合时,最好能指定集合大小,既是桶的大小,因为,桶的大小与Map中元素发生冲突有关,Map在处理元素冲突是很消耗性能

5. 除非有必要,否则尽量不要使用线程安全集合,因为,集合在维护线程安全过程中需要消耗一部分性能

五 IO流

1.IO流和NIO流区别?

答:

1.IO流是以字节的方式读写,而NIO流是以块的方式读写,在性能方面NIO流占优势

2.IO流是阻塞流,而NIO流可以通过Selector类来实现非阻塞流,避免线程占用资源

2.画出IO流和NIO流的类图?

(由于时间问题,暂时不写)

六 网络编程

1.如何手工实现SSL加密数据(以及类图)

2.简述使用JDBC连接数据库过程

答:

1.通过Class.forName()加载数据库管理驱动程序,并实例化成DriverManger

2.从DriverManeger驱动管理器中获取连接对象Connection

3.通过Connection连接对象创建Statement来执行SQL操作或打开事务

4.关闭statement和Connection

3.Socket网络编程

服务器端:

1.指定端口构建ServerSocket对象

2.调用accept()函数阻塞直到有客户连接,生成Socket客户连接对象

3.通过客户Socket获取对应的输入和输出流,并与之交互

4.关闭输入和输出流及客户Socket

5.最后关闭服务器ServerSocket

public class Server {
public static void main(String args[]){
ServerSocket ssocket=null;
Socket client=null;
try {
ssocket = new ServerSocket(5550);//构建服务器ServerSocket,指定端口5550
client = ssocket.accept();//阻塞等待客户连接
System.out.println("accepted a connection");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));//输入流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));//输出流
String message;
while(!(message=br.readLine()).equals("bye")){
System.err.println("client:"+message);
bw.write("request:"+message+"\n");
bw.flush();
}
br.close();//关闭输入和输出流
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try{	<pre name="code" class="java"><span style="white-space:pre">				</span>if(client!=null) client.close();//关闭客户socket及服务器socket
if(ssocket!=null) ssocket.close();} catch (IOException e) {// TODO Auto-generated catch block}}}}


客户端:

1.构建连接服务器Socket,指定主机IP和端口

2.通过服务器Socket获取对应的输入和输出流,并与之交互

3.关闭输入和输出流及连接服务器Socket

public class Client {
public static void main(String args[]){
Socket server=null;
try{
server = new Socket("127.0.0.1",5550);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(server.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(server.getInputStream()));
bw.write("hello\n");
bw.flush();
System.out.println("server:"+br.readLine());
bw.write("bye\n");
bw.flush();
System.out.println("客户端结束");
br.close();
bw.close();
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(server!=null) server.close();
}catch(IOException e){

}
}
}
}


4.基于Java方式实现与Web服务器交互

1.构建URL对象

2.由URL对象打开一个URL连接生成URLConnection,根据协议可以强制转化成HttpURLConnection或HttpsURLConnection对象,获取指定操作

3.有URLConnection对象获取InputStream流,读取数据

4.关闭InputStream流

public class ConectionWeb {
public static void main(String args[]){
InputStream input =null;
HttpURLConnection connection=null;
try {
URL url = new URL("http://www.baidu.com");
connection= (HttpURLConnection) url.openConnection();//打开连接
input= connection.getInputStream();//获取输入流
byte data[]=new byte[1024];
int size=-1;
while((size=input.read(data))!=-1)//读取数据
System.out.print(new String(data,0,size));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try{
if(input!=null)input.close();//关闭流
}catch(IOException e){}
}
}
}


七 对象序列化

1.对象序列化有哪些注意事项

1.序列化对象时忽略静态属性和被关键字transient修饰的属性

2.可以在序列化类中使用private void writeObject(ObjectOutputStream o)和private void writeObject(ObjectInputStream o)来添加额外操作时,并手动调用o.defaultWriteObject()或o.defaultReadObject()函数,因为那两个方法覆盖了默认序列化操作

3.默认不添加serialVersionUID,系统会根据class类使用特定摘要算法生产serialVersionUID,如果修改类class类中的任何地方将会导致serialVersionUID不同,在反序列化时由于版本不一样,会抛出错误

http://developer.51cto.com/art/201202/317181.htm

/article/4676439.html

2.如何实现对象序列化

public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private int age;
private String name;
public Person(String name,int age){
this.name=name;
this.age=age;
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.err.println("writeObject 被调用");
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.err.println("readObject 被调用");
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
public static void main(String args[]){
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
String filePath = "c:\\person.dt";//文件路径
try {
oos = new ObjectOutputStream(new FileOutputStream(filePath));
ois = new ObjectInputStream(new FileInputStream(filePath));
oos.writeObject(new Person("lzq",24));//写入对象
oos.close();
System.out.println(ois.readObject());//读对象,并输入到控制台
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try{
if(ois!=null)ois.close();
}catch(IOException e){}
}
}
}
结果:

writeObject 被调用
readObject 被调用
Person [age=24, name=lzq]


3.对象序列化技术适用用在何种情况

1.分布式处理,如:在不同JVM虚拟机中的通信,对象在某台虚拟机中实现,然后通过序列化对象传送给另一个虚拟机

2.需要保存虚拟机中的对象,如:想重启虚拟机,但右想重启后在还原虚拟机中的环境

4.对象序列化有几种方式,它们之间有什么区别

1.使用Serializable接口(例子题2)

2.使用Externalizable接口,注意使用Externalizable接口时一定要提供默认的构造函数,JVM虚拟机默认是先调用默认构造函数构造对象,然后在通过接口函数赋值给属性,而Serializable接口不会调用构造函数来构造对象

public class PersonByExternalizable implements Externalizable{
private static final long serialVersionUID = 1L;
private int age;
private String name;
public PersonByExternalizable(String name,int age){
this.name=name;
this.age=age;
}
public PersonByExternalizable(){
System.err.println("构造函数被调用");
}
@Override
public void readExternal(ObjectInput arg0) throws IOException,
ClassNotFoundException {
// TODO Auto-generated method stub
this.age=arg0.readInt();
this.name=(String)arg0.readObject();
}
@Override
public void writeExternal(ObjectOutput arg0) throws IOException {
// TODO Auto-generated method stub
arg0.writeInt(this.age);
arg0.writeObject(name);
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
public static void main(String args[]){
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
String filePath = "c:\\personByExternalizable.dt";//文件路径
try {
oos = new ObjectOutputStream(new FileOutputStream(filePath));
ois = new ObjectInputStream(new FileInputStream(filePath));
oos.writeObject(new PersonByExternalizable("lzq",24));//写入对象
oos.close();
System.out.println(ois.readObject());//读对象,并输入到控制台
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try{
if(ois!=null)ois.close();
}catch(IOException e){}
}
}
}
结果:

构造函数被调用
Person [age=24, name=lzq]


八 高级应用

1.java反射技术

答:Java反射机制,就是JVM能在运行期,通过Class来访问或调用对象中原始信息(属性,方法,构造函数,已实现接口,父类),甚至构造实例。

public class Reflection extends Parent implements Interface{
public String name;
private int age;
public Reflection(){}

public Reflection(String name, int age) {
super();
this.name = name;
this.age = age;
}
private void myIsPrivateMethod(){}

public void setName(String name) {
this.name = name;
}

public static void main(String args[]) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Class<Reflection> reflection=Reflection.class;
System.err.print("已实现的接口:");
Class interfaceIml[] = reflection.getInterfaces();
System.err.println(interfaceIml[0].getName());

System.err.print("\n父类:");
Class parent=reflection.getSuperclass();
System.err.println(parent.getName());

System.err.print("\n打印构造函数数目:");
Constructor<?>[] cs = reflection.getConstructors();
System.err.println(cs.length);

System.err.println("\n打印public函数名:");
Method[] methodByPublic=reflection.getMethods();
for(Method m:methodByPublic) System.err.println(m.getName());

System.err.println("\n打印全部函数名,包括私有的");
Method[] methodAll=reflection.getDeclaredMethods();
for(Method m:methodAll) System.err.println(m.getName());

System.err.println("\n打印public属性名:");
Field[] fields=reflection.getFields();
for(Field f:fields)System.err.println(f.getName());

System.err.println("\n打印所有属性名:");
Field[] fieldAll=reflection.getDeclaredFields();
for(Field f:fieldAll)System.err.println(f.getName());

System.err.println("\n调用构造函数创建实例:");
Constructor constructor = reflection.getConstructor(String.class,Integer.TYPE);
Object obj = constructor.newInstance("lzq",24);
System.err.println(obj);

System.err.println("\n调用setName(String ..)方法设置对象名:");
Method method = reflection.getMethod("setName", String.class);
method.invoke(obj, "qzl");
System.err.println(obj);

}

@Override
public String toString() {
return "Reflection [name=" + name + ", age=" + age + "]";
}

}
abstract class Parent{

}
interface Interface{

}
结果:

已实现的接口:Interface

父类:Parent

打印构造函数数目:2

打印public函数名:
toString
setName
main
getClass
hashCode
equals
notify
notifyAll
wait
wait
wait

打印全部函数名,包括私有的
myIsPrivateMethod
toString
setName
main

打印public属性名:
name

打印所有属性名:
name
age

调用构造函数创建实例:
Reflection [name=lzq, age=24]

调用setName(String ..)方法设置对象名:
Reflection [name=qzl, age=24]


2.JNI技术

参考:/article/5587877.html

3.大数字运算

答:大数据运算主要跟2个类有关,分别为BigInteger(整数)和BigDecimal(浮点)

public class BigArithmetic {

public static void main(String args[]){
BigInteger bigInteger1=new BigInteger("123456789");
BigInteger bigInteger2=new BigInteger("987654321");
System.out.println(bigInteger1.toString()+"*"+bigInteger2.toString()+"="+bigInteger1.multiply(bigInteger2));
BigDecimal bigDecimal1=new BigDecimal("123456789.334");
BigDecimal bigDecimal2=new BigDecimal("987626.334");
System.out.println(bigDecimal1.toString()+"*"+bigDecimal2.toString()+"="+bigDecimal1.multiply(bigDecimal2));
}
}
结果:

123456789*987654321=121932631112635269
123456789.334*987626.334=121929176257348.721556


4.日志管理系统

参考:http://www.blogjava.net/DLevin/archive/2012/11/08/390992.html

5.远程方法调用RMI

参考:http://haolloyin.blog.51cto.com/1177454/332426/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: