JAVA常见问题总结

一 基本类型

  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

http://www.cnblogs.com/xdp-gacl/p/3777987.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技术

参考:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.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/





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值