- 方法重写要点:
- 获得某个类对应Class对象的方式:
- 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); } }