1 java数据类型可以自动向上转,但是不能向下转。
比如int a =1; short s = a;//报错2 小数默认是double双精度的。单精度要加上f。
比如0.3是double型的,0.3f才是float型的。3 字符串问题。java和c++一样有个常量池。字符串常量就存放在那里。
String s = "abc"; s指向常量池的 “abc” String s1 = new String("abc");用常量池的"abc"初始化堆里面的s1。 String的intern()方法返回他在常量池里面的引用(指针?),如果没有,那么先在常量池创建再返回。 常量池里面的数据是无法修改的。String的replace方法会返回一个新的字符串。4 hashtable和hashmap。
hashtable是线程安全的(有synchronized修饰) hashmap不是线程安全的,但是可以存放一个为null的键值和value。5 参数传值还是引用。java都是按值传递。当传递基础类型的时候传递数据的副本。当传递对象的时候,传递对象引用的副本(指针的值?)。
6 java内存回收。jvm会自动清除没有被指向的对象(c++里面的引用计数?)。那么对象的指向是什么意思呢(即引用计数是如何工作的?)。
void fun(){ A a = new A(); }a在fun调用结束后被释放,所以 a指向的内存使用计数减1。 A a = new A(); a = null;赋值为null,引用计数减1。 a = b; 赋其他值,引用计数减1。 通过调用System.gc()可以强制执行一次垃圾回收。(System.gc()其实是对Runtime.getRuntime().gc()的简单包装)7 static class
只有内部类可以声明为static class
static 内部类和非static 内部类有以下区别: a static内部类只能访问外部类的static方法或者成员。非static内部类可以访问非static方法和成员(当然也可以访问static成员和方法) b static内部类可以声明shatic方法和成员,非static内部类不能声明static方法或者成员 c static内部类可以单独初始化。Inner i = new Outer.Inner(); 非static内部类Outer o = new Outer();Inner i = o.new Inner();8 内部类可以访问外部类的private方法或者变量
9 final成员变量必须在声明时初始化。如果是static final,可以在static块里面初始化。
10 Base base = new Derived(); Derived是Base的派生类
base instanceof Base 为true base instanceof Derived为true11 重写equals要遵守的规范(如果不准照这个规范,集合类在操作时会出问题):
自反性:x.equals(x)肯定为true 对称性:x.equals(y) 为true,那么y.equals(x)肯定为true 传递性:x.equals(y) 为true,y.equals(z)为true,那么x.equals(z)肯定为true 一致性:x.equals(y) 为true,在x,y未改变的时候多次比较依然为true12 Object的getClass()方法返回真实的classname
Base base1 = new Derived(); base.getClass()返回Derived。13 java的hashcode用于散列函数。该函数与equal紧密相关,在覆盖了equal的时候必须覆盖hashcode方法。并且要准照以下规范
a 在程序运行期间,只要equal方法用到的信息没有被修改,那么hascode返回的数值必须一致。多次运行程序则不必相等。 b 两个对象equal为true,那么hashcode值也必须相等。 c 两个对象equal为false,那么hashcode值可以相同也可以不相同,但是不同的话可以提高散列表的性能。14通过java反射只能调用对象的public方法,否则会报错:java.lang.NoSuchMethodException。static域也是同样的,查阅资料说setAccessible方法可以修改反问权限,试了没有效果。
15 对象clone。Object的clone方法是protected的本地方法,他可以对对象进行逐域拷贝。要使用clone方法,必须重载clone方法,并将其设置为public的。然后调用super.clone(),但是这时候会抛异常,因为类必须要实现Cloneable接口才具备Object的clone功能。当然我们也可以不使用Object的clone方法,转而自己new一个对象,然后逐域赋值。注意,object的clone只是一个浅拷贝。如果类成员变量是基础类型是没有问题的,但如果存在对象变量,那么这个时候默认的clone其实只是拷贝的对象的引用(指针?),变量对象是共享的。如果要实现深拷贝,只有堆变量进行依次clone。
16 访问权限控制
protected除了子类可见,并且包内可见。这和c++不一样,c++的protected只有子类可见。 子类继承的时候,不允许缩小基类方法的访问权限,避免无法正常使用基类方法。(java编译就会报错) 接口方法必须全是public的17 java的List(线性表)共有3种实现
ArrayList和c++的Vector一样,也是可变长度数组。在添加元素的时候可能导致数组元素的移动 Vector,和ArrayList差不多,但是增加线程同步,所以效率会比ArrayLIst低 LinkedList,链表实现。18 StringBuffer是线程安全的(基本废弃),StringBuilder不是线程安全的。
19 java同c++一样,不要在构造函数里面调用虚方法(java里被子类覆盖的方法)。java里面的clone方法实现和构造器实现很相似,所以不能在clone方法里面调用虚方法。
20 基类数组可以指向子类数组,但是泛型不可以
Object[] objs = new Integer[10]; //ok ArrayList<Object> list = new ArrayList<Integer>();//错误21 java泛型(c++模板)同函数重载(overload)一样都是编译期行为。覆盖(c++虚函数)都是运行期行为
22 c++中的对象可以在栈上创建,但是java不行,只能通过new 在堆上创建
public class Base{ public Integer INT_VALUE = 0; public Base(){ show(); } public Base(int v){ INT_VALUE = v; } public void show(){ System.out.println("base show------>"+INT_VALUE); } }在java中 Base b;是不会调用构造函数的,而在c++中是可以的。
23. i++和 ++i都不具有原子性。
24.volatile变量修饰符符使线程在获取变量值的时候每次都从内存去取,而不是寄存器中(线程栈?)获取。保证变量修改的及时性。
示例 public class MyThread extends Thread{ private volatile boolean pleaseStop = false; @Override public void run(){ while (!pleaseStop) { //如果不加volatile,那么每次都是取的线程内部的副本(每个线程都有单独的线程栈,或者说cpu和内存间的高速缓存?) } System.out.println("thread end---------------->"); } public void tellMeToStop() { pleaseStop = true; } } MyThread thread = new MyThread(); thread.start(); try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } thread.tellMeToStop();//如果不加volatile。那么这句话无法停掉线程25.java同步的方法。
a.synchronized关键字,修饰方法或者语句块。 b.使用Lock(ReentrantLock),和synchronized有相同的效果,但必须放在try catch中,避免异常的时候无法释放锁。和synchronized区别有以下3点: b1:等待可中断,线程长期持有锁的时候,等待的线程可以选择放弃,避免死锁 b2:可以创建公平锁(按照申请顺序获得锁,默认是非公平锁,当然公平锁会消耗性能) b3:可以绑定多个对象26.java引用类型。
⑴强引用(StrongReference):Object obj = new Object();没有引用的时候才会删除。否则不会删除改对象 ⑵软引用(SoftReference):空间不足的时候就会回收。否则不会回收。SoftReference<A> softReference = new SoftReference<A>(new A()); ⑶弱引用(WeakReference):等于没有引用。垃圾回收的时候直接回收。但是垃圾回收有个周期,所以会短暂持有一段时间 ⑷虚引用(PhantomReference):等于没有引用。和弱引用的区别在于,他必须和引用队列ReferenceQueue联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。 ReferenceQueue queue = new ReferenceQueue (); PhantomReference pr = new PhantomReference (object, queue);27.Serializable序列化。
a.serialVersionUID表示序列化的版本,只有版本相同才可以进行反序列化。 b.反序列化的时候并不会调用构造器。 c.可以用父类对象反序列化派生类对象。 d.非静态内部类不应实现Serializable。因为他对如何保存外部类没有明确规定。28.ThreadLocal是为每一个线程分配一个变量副本。各个线程之间互不干涉。
29.sleep(),wait(),notify(),yield() 区别:
sleep:指定当前线程休眠一定时间。不释放对象锁,就是说如果有synchronized同步块,其他线程不能访问共享数据 yield:和sleep差不多,但是不能指定休眠时间,并且只能让同优先级的线程有执行的机会 wait:让线程休眠指定时间,与sleep不同之处在于该方法必须在synchronized同步块内使用,他会释放对象锁。 notify:让wait的线程恢复执行。