找工作复习之java基础篇

时间:2022-06-29 15:32:49

  • 方法重写要点:
            1. 子类中方法与父类中的方法返回值类型,方法名,参数列表完全相同。
            2. 子类方法的修饰符级别不能低于父类的方法访问级别。
            3. 子类抛出的异常类型的范围不能大于父类所抛出异常的范围。
  • 获得某个类对应Class对象的方式:
            1. 使用类的.class语法;
            2. 通过类对象的getClass()方法;
            3. 通过Class对象的forName()方法获得
            4. 对于包装类,可以通过.TYPE语法获得;
  • final关键字
            1. final用于类,表示该方法不可被继承。
            2. final用于变量,表示该变量不可被修改。
            3. final用于方法,表示该方法不可被重写。
package com.cao.basics;
/**
 * final关键字探测
 * @author caoqingrong
 *
 */
public class Test {

	private final int a;
	
	private String name;
	
	public Test(){
		a = 3;
	}
	
	public Test(String name){
		this.name = name;
	}
	
	/**
	 * 该类无法编译通过,因final修饰的属性a可能没有被初始化
	 * final修饰的成员变量有以下集中初始化方式:
	 * 1.声明变量时直接赋值;
	 * 2.在构造方法中赋值,但要注意,如有多个构造方法时,每个构造方法中都得赋值。
	 * 3.如果该成员变量还有static关键字修饰,那么只能在其声明的时候赋值。
	 */
}
看看下面的例子:
public class Test {
	//用final关键字声明引用类型成员变量
	private static final StringBuffer sb = new StringBuffer();
	
	public static void main(String[] args) {
		sb.append("abc");  //该行编译通过
		//sb = new StringBuffer();  //该行编译不通过
		
		/**
		 * 小结:对于final关键字修饰的引用类型的成员变量不可更改是指其引用不可修改,其内容是可以修改的
		 */
	}
}
  • 关于try...catch...finally
    public class Test {
    	public static void main(String[] args) {
    		try{
    			String str = null;
    			//return;
    			System.exit(0);
    		}catch (Exception e) {
    			System.out.println("catch block!");
    		}finally{
    			System.out.println("finally block!");
    		}
    	}
    }
  • 关于数组
public class ArraryInterfaceTest {

	public static void main(String[] args) {
		I[] i = new I[2];//编译通过,数组存放对象的地址
		//I i2 = new I();//编译不通过,不能实例化接口类型
		
		i[0] = new J();
		i[1] = new J();
	}
}

interface I{
}

class J implements I{
}
  • 关于异常

 java异常都是继承自java.lang.Throwable类的,java异常分为两种:

(1)checked Exception :必须处理,捕获处理或继续抛出;除运行时异常,别的都是检查异常;

常见checked Exception:NoSuchMethodException、IllegalClassFormatException、DataFormatException、ClassNotFoundException、SQLException

(2)uncheckedException(即:runtimeException):可以不做任何处理,也可以捕获或抛出;运行时异常都继承自RuntimeException,指那些在java虚拟机正常运行期间抛出的异常的超类。

常见的RuntimeException:NullPointerException、UnknownTypeException、SystemException、ClassCastException、BufferOverflowException、IllegalArgumentException等

  • 为什么public final修饰的变量经常要加上static修饰?(public static final sts = "A";)

答案:为了节省内存,因为对于final修饰的属性,在每个对象中都是不能被修改的,只能读,所以用static修饰,作为类变量,这样可节省空间。

  • 关于hashcode
package com.cao.basics;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
 * hashCode 探究
 * @author caoqingrong
 *
 */
public class HashSetTest {
	
	public static void main(String[] args) {
		
		Set<String> set = new HashSet<String>();
		
		System.out.println(set.add("xyz"));   //true
		System.out.println(set.add("abc"));   //true
		System.out.println(set.add("xyz"));   //false
		
		for(Iterator<String> iter = set.iterator();iter.hasNext();){
			System.out.println(iter.next());
		}
		
		System.out.println("==================看看下面喽=======================");
		/*==================================================================*/
		
		Set<People> ps = new HashSet<People>();
		
		System.out.println(ps.add(new People("zhangsan")));   //true
		System.out.println(ps.add(new People("lisi")));		  //true
		System.out.println(ps.add(new People("zhangsan")));	  //true
		
		for(Iterator<People> iter = ps.iterator();iter.hasNext();){
			System.out.println(iter.next().getName());
		}
		
		/**
		 * 总结:
		 * 	  1.当向集合set中添加对象时,首先集合计算要增加对象的hashCode码,根据该hashCode码来计算一个位置来存放欲添加对象,如果该位置不存在已有对象,那么集合set认为该对象在集合中不存在,
		 * 	             直接添加进去。如果已存在一个对象,则集合会调用该对象的equals方法,判断欲增加对象与已有对象比较,如果返回false则认为集合中不存在,如果返回true,则认为已存在,不会将该对象加入集合。
		 *    2.当重写equals方法时,必须重写hashCode方法。其中有个原则:如果一个类的两个对象使用equals方法比较时,结果为true,那么两个对象必须具有相同的hashCode。
		 */
		
	}
}

class People{
	private String name;
	
	public People(String name){
		this.name = name;
	}
	
	public String getName(){
		return name;
	}
	@Override
	public boolean equals(Object obj) {
		if(this == obj){
			return true;
		}
		if(obj instanceof People){
			if(null != obj && this.name.equals(((People) obj).name)){
				return true;
			}
		}
		return false;
	}
	@Override
	public int hashCode() {
		return name.hashCode();
	}
	
}
  • 题目:请说出hashCode方法,equals方法,HashSet,HashMap之间的关系?

1.HashSet底层使用HashMap实现的;

2.HashMap的key就是放进HashSet的对象,value是一个objec常量t对象;

3.HashMap底层用数组实现。

4.当向HashMap中增加一个对象时,将会调用该对象的hashcode方法获得其hashCode值,然后根据该值计算出一个数组的下标索引(计算数组的一个位置)。

5.将要增加的对象与该位置上的对象进行比较(equals方法),如果相同,那么将该位置上的已有的对象(Entry类型)的value替换掉,如不不相同,则沿着该Entry的链继续重复上述过程,如果到链的最后仍然没有找到与此对象相同的对象,那么这个时候会将该对象增加到数组中,将数组中该位置上的那个Entry对象链接到该对象后面。

6.对于HashSet和HashMap,这样做是为了提高其元素查找效率,使得查找时间不随着Set或Map的大小改变而改变。

  • 题目:ArrayList、LinkedList和Vector的区别?

1.ArraryList和Vector都是通过数组实现的,ArrayList所有方法都不是同步的,Vector大部分public方式是同步的,因此Vector是线程安全的,也正因为如此,在不考虑多线程的情况下,ArraryList效率较高。

2.LinkedList底层采用链表实现,故LinkedList增加和删除元素的效率很高,而ArrayList相对更差,但由于ArraryList数组实现,其元素是顺序存储的,所以其元素检索速度很快,优于LinkedList。

  • 题目:&和&&的区别?

他们都可以作为逻辑运算符,区别是&&短路,而&不短路。此外&为位运算符,如3&5的结果为1。(换算成二进制进行与运输)

  • 关于内部类:
  • package com.cao.basics;
    
    import java.util.Date;
    
    public class InnerClassTest {
    
    	@SuppressWarnings("deprecation")
    	public String getDateStr(Date date){//注意:该参数date为匿名内部类的实例,而非Date的实例。
    		return date.toLocaleString();
    	}
    	public static void main(String[] args) {
    		InnerClassTest ict = new InnerClassTest();
    		
    		String result =  ict.getDateStr(new Date(){//匿名内部类,该类为Date的子类
    			public String toLocaleString(){//重写Date类的toLocaleString()方法
    				return "hell world!";
    			}
    		});
    		System.out.println(result);
    		
    		/**
    		 * 总结:java有四种内部类,分别为
    		 * 1.静态内部类;static inner class
    		 * 2.成员内部类;member inner class
    		 * 3.局部内部类;local inner class
    		 * 4.匿名内部类;anonymous inner class
    		 */
    	}
    }
    


  • 关于泛型
  • package com.cao.basics;
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    public class GenericExtendsTest {
    
    	public void method1(List<Object> list){
    		
    	}
    	
    	public void method2(){
    		method1(new ArrayList<Object>());
    		method1(new ArrayList<String>());
    		method1(new ArrayList<Integer>());
    	}
    	
    	//method1、method2是否编译通过?答案:不通过。
    	
    	public void method3(List<? extends Object> list){
    		
    	}
    	
    	public void method4(){
    		method3(new ArrayList<Object>());
    		method3(new ArrayList<String>());
    		method3(new LinkedList<Integer>());
    	}
    	//method3、method4是否编译通过?答案:通过。
    	
    	public void method5(List<?> list){
    		
    	}
    	
    	public void method6(){
    		method5(new ArrayList<Object>());
    		method5(new ArrayList<String>());
    		method5(new LinkedList<Integer>());
    	}
    	//method5、method6是否编译通过?答案:通过。
    	/**
    	 * 结论:
    	 * 1.关于泛型的继承ArrayList<Object> 继承了  List<Object>类型,而ArrayList<String> 并非继承 List<Object>.
    	 * 2.List<?> 等价于 List<? extends Object>
    	 * 
    	 */
    	
    }
    


  • 多线程:wait、notify、notifyAll、以及sleep方法的联系与区别?

1.如果某个线程调用了某个对象的wair方法,那么该线程必须拥有该对象的锁(换句话说,如果一个线程调用了某个对象的wait方法,那么wait方法必须要在synchronized中)。

2.如果一个线程调用了某对象的wait方法,那么该线程就会释放该对象的锁。

3.在java对象中,有两种池(锁池和等待池)

4.如果一个线程调用了某个对象的wait方法,那么该线程就进入该对象的锁池中(释放锁),如果未来的某一时刻,另外一个线程调用了该对象的notify或notifyAll方法,那么在该对象等待池中线程就会起来进入对象的锁池中,去等待获得该对象的锁,如果获得锁成功后,那么该线程将继续沿着wait之后的路径去执行。

5.sleep(long time),如果一个线程调用了sleep方法,那么在睡眠的同时,它不会失去对象的锁的所有权。

  • 关于synchronrized关键字

1.在某个对象的所有synchronized方法中,在某一时刻,只能有一个唯一的一个线程去访问这些synchronized方法。

2.如果一个方法是synchronized方法,那么该sycchronized关键字表示给当前对象上锁(即this);

3.如果一个synchronized方式是静态的,那么该synchronized关键字表示给对象锁对应的Class对象上锁。(每个类不管生成多少个对象,其对应的Class对象只有一个)。

package com.cao.basics.Thread;

public class ThreadSynchTest {

	public static void main(String[] args) {

		C c = new C();
		T1 t1 = new T1(c);
		//c = new C();
		T2 t2 = new T2(c);
		Thread t = new Thread(t2);
		
		t1.start();
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		t.start();
	}

}
class C{
	//private Object object1 = new Object();
	//private Object object2 = new Object();
	public synchronized void hello(){  //static
		//synchronized (object2){
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("HELLO");
		//}
		
	}
	public synchronized void world(){ 
		//synchronized(object1){
			System.out.println("WORLD");
		//}
	}
}

class T1 extends Thread{
	private C c ;
	
	public T1(C c){
		this.c = c;
	}
	
	@Override
	public void run() {
		c.hello();
	}
}

class T2 implements Runnable{
	
	private C c;
	
	public T2(C c){
		this.c = c;
	}

	@Override
	public void run() {
		c.world();
	}
	
}


  • 在Java中一个字符是否可以表示汉子?

可以,java中 char表示的长度是16位。如下:

public class CharTest {
	public static void main(String[] args) {
		char c = '好';
		System.out.println(c);
	}
}