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关键字修饰的引用类型的成员变量不可更改是指其引用不可修改,其内容是可以修改的
*/
}
}
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等
答案:为了节省内存,因为对于final修饰的属性,在每个对象中都是不能被修改的,只能读,所以用static修饰,作为类变量,这样可节省空间。
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 set = new HashSet();
System.out.println(set.add("xyz")); //true
System.out.println(set.add("abc")); //true
System.out.println(set.add("xyz")); //false
for(Iterator iter = set.iterator();iter.hasNext();){
System.out.println(iter.next());
}
System.out.println("==================看看下面喽=======================");
/*==================================================================*/
Set ps = new HashSet();
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 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();
}
}
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的大小改变而改变。
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
1.如果某个线程调用了某个对象的wair方法,那么该线程必须拥有该对象的锁(换句话说,如果一个线程调用了某个对象的wait方法,那么wait方法必须要在synchronized中)。
2.如果一个线程调用了某对象的wait方法,那么该线程就会释放该对象的锁。
3.在java对象中,有两种池(锁池和等待池)
4.如果一个线程调用了某个对象的wait方法,那么该线程就进入该对象的锁池中(释放锁),如果未来的某一时刻,另外一个线程调用了该对象的notify或notifyAll方法,那么在该对象等待池中线程就会起来进入对象的锁池中,去等待获得该对象的锁,如果获得锁成功后,那么该线程将继续沿着wait之后的路径去执行。
5.sleep(long time),如果一个线程调用了sleep方法,那么在睡眠的同时,它不会失去对象的锁的所有权。
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中 char表示的长度是16位。如下:
public class CharTest {
public static void main(String[] args) {
char c = '好';
System.out.println(c);
}
}