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