public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub byte a = 3,b=2; //1 byte c = a+b; //2 System.out.println(c); } }
public class PerttyTest { public static void main(String[] args){ String i="123",s; s=getStr(i); System.out.println(s); } public String getStr(String s){ StringBuffer sb=new StringBuffer(); for(int i=s.length()-1;i>=0;i--){ sb.append(s.charAt(i)); } return sb.toString(); } }
class ExBase{ abstract public void martley(){ } } public class MyEx extends ExBase{ public static void main(String argv[]){ DataInputStream fi =new DataInputStream(System.in); try{ fi.readChar(); }catch(IOException e){ System.exit(0) } finallly{Sytemt.out.println("Doing finally");} } }
class ShallowCopy implements Cloneable{ private Date begin; public Date getBegin() { return begin; } public void setBegin(Date begin) { this.begin = begin; } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } } class DeepCopy implements Cloneable{ private Date begin; public Date getBegin() { return begin; } public void setBegin(Date begin) { this.begin = begin; } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub DeepCopy obj=null; obj=(DeepCopy) super.clone(); obj.setBegin((Date) getBegin().clone()); return obj; }
public class Test1 { public int i; public Test test; public Test1() { // TODO Auto-generated constructor stub } public Test1(Test1 t){ i=t.i; test = new Test(); test.i=t.test.i; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //A a = new B(); Test1 t = new Test1(); t.i=9; t.test=new Test(); t.test.i=10; Test1 t1=new Test1(t); System.out.println(t1.i); System.out.println(t1.test.i); } } class Test{ public int i; public Test(){ } public Test(Test t){ i=t.i; } }
public class Test1{ public static void main(String args[]){ String a="1234"; String b="1234"; String c = new String("1234"); System.out.println(a==b); System.out.println(a==c); System.out.println(a.equals(c)); } }
equal()方法是java.lang.object的方法,也就是所有的Java类都会有的方法。它可以被程序员覆盖重写,通过自定义的方式来判定两个对象是否相等。对于字符串String类来说,他的equal方法用来比较字符串的字符序列是否 完全相等。
Java中char采用Unicode编码格式,用两个字节来表示一个字符,一共16bit,它所能表示的最大值为2的16次方
char是可以存储汉字的,每个中文字符都有对应的Unicode编码。
子类覆盖父类的方法时,不能够降低父类方法的可见性,即父类的public方法不能覆盖为private,解释:
void func(SuperClass sc) { sc.foo(); } SuperClass sc = new ChildClass(); func(sc);
public class Test1 { public Test1() { // TODO Auto-generated constructor stub } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub A a = new B(); System.out.println("----------------"); B b = new B(); } } class A{ static{ System.out.println("AAAAAAAAAAAAAA static"); } public A() { //super(); System.out.println("AAAAAAAAAAAAAA"); // TODO Auto-generated constructor stub } } class B extends A{ static{ System.out.println("BBBBBBBBBBBBBBB static"); } public B() { //super(); System.out.println("BBBBBBBBBBBBBB"); } }
"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在 任何时候都可能被垃圾回收。 虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队 列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
Java虚拟机在执行这段代码时,遇到双引号操作符,它会自动创建一个String对象,该String对象所代表的值就是abc,然后再返回该对象的一个引用。
对应str1字符串来说,它的创建过程同上所述。在Java5.0及其以后的版本,在创建该对象之前,JVM会在String对象池中去搜索该字符串对象是否已经被创建,如果已经被创建,则直接返回一个引用,否则先创建再返回引用。
而str2字符串变量,它的创建过程就要多一个步骤。它会额外的创建一个新的String对象,也就是new关键字的作用,并且返回一个引用给str2 。
Java中有对象池的概念,Java虚拟机启动时候会实例化9个对象池,分别用来存储8中基本类型的包装类和String对象。对象池的存在是为了频繁的创建和销毁对象而影响系统性能。
str1是在对象池中取对象,str2方法直接生成新的对象。
任何情况下,只要new一个String对象都是创建了新的对象。
因此表达式str1==str2的结果是false的。
Vector与ArrayList都是List的实现类,它们都代表链表形式的数据结构。Vector是线程安全的,因为它操作元素的方法都是同步方法,而ArrayList则不是。开发过程中应该根据需要进行选择,如果需要保证线程安全的地方则需要使用Vector,而不必要的时候则无需使用Vector,因为ArrayList效率会高一些。
对于Map接口来说,它有两种比较重要的实现类HashMap和HashTable,它们保存元素的时候都是无序的。
HashTable的方法是同步的,HashMap不同同步。所以在多线程场合要使用HashTable,这个区别就行Vector和ArrayList一样。
HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。
HashTable有一个contains方法,功能和containsValue()一样。
HashTable使用Enumeration,HashMap使用Iterator。
HashTable中hash数组的初始化大小及其增长方式不同。
本题目主要考察的是面试者对FileInputStream和FileOutputStream的使用,本质上也就是先从一个文件读出数据,然后再往另外一个文件写入数据。
FileInputStream类中最主要的是read()方法,通过它把数据从流中读到内存里来。read()方法的参数为一个byte数组,有一点像缓存,也就是把数据先读到内存中暂存,然后再进行相关操作。
FileOutputStream是用于打开一个输出流的,这里就需要把byte数组中的数据写入到输入流中。
public static void main(String args[]){ FileInputStream fin = null; FileOutputStream fou = null; try { fin = new FileInputStream("read.txt"); fou = new FileOutputStream("write.txt"); byte[] buff = new byte[512]; int len; while((len=fin.read(buff))>0){ fou.write(null, 0, len); } fin.close(); fou.close(); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally{ } }
InputSteam和OutputStream都只能单方面的读和写文件的内容,如果有随机的读取和写入文件的内容的需要那又该怎么办呢?Java为开发者提供了一个RandomAccessFile类,它就是专门用来随机存取文件内容的。
RandomAccessFile类操作文件内容的时候,就好像操作一块内存区域一样,把字节用下标来进行定位,通过调用RandomAccessFile的API方法,把指针的指向进行移动,达到随机存取数据的目的。
用length()方法获取文件的内容长度。
用seek()方法随机的到达任何需要存取数据的地方。
调用read()方法获取当前位置的数据,用write()方法写入数据。
完成需要以后,调用close()关闭文件。
字节流是I/O中最原始的方式,因为计算机处理数据总是以一个byte为基本单位的,字节流就是每次读取的单位为byte。I/O流总是分为两端的,一端作为输出,一端作为输入,因此就可以把流分为输入流和输出流。Java中的基础字节输入流和输出流的类为:InputStream和Outputstream。通过它们可以再衍生出FileInputStream和FileOutputstream、ObjectInputStream和ObjectOutputstream、BufferInputstream和BufferOutputStream等。
字节流最大的特点就是每次的输出和输入都是一个字节。注意的操作对象就是byte数组,通过read()和write()方法把byte数组中的数据写入或读出。
针对文本文件,Java提出了字符流的概念,使用字符流来写入和读出字符数据。无需再使用字节流进行包装。
字符流是由字节流包装而来,它的输入和输出流类型包括StringReader和StringWriter、BufferReader和BufferWriter。对于前者,它们的使用方法与字节流类似,主要还是read()和write()方法,而后者除了基本的read()和write()以外,有一个功能是在读取文章类型的文本文件时经常需要的,那就是readLine()方法。
字符流对象的创建的时候,一般是需要提供一个输入或输出流的。例如,在创建BufferedReader或BufferedWriter对象的时候,需要提供一个InputStreamReader或InputStreamWriter对象,另外,对于特定字符格式的文本内容,还需要再创建InputStreamReader或InputStreamWriter对象的时候,提供字符格式类型作为构造方法的参数。
public static void main(String args[]){ try { InputStream is = new FileInputStream("a.txt"); InputStreamReader isr = new InputStreamReader(is, "GBK"); BufferedReader br = new BufferedReader(isr); StringBuffer sb = new StringBuffer(); String str=null; while((str=br.readLine())!=null){ sb.append(str); } br.close(); } catch (FileNotFoundException e2) { // TODO Auto-generated catch block e2.printStackTrace(); }catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }
继承Thread类和实现Runable接口,其实Thread是实现了Runnable接口的,就是说,本质上线程类是需要试下Runnable接口,只是Thread还提供了一些额外的方法。
继承Thread类,重写父类run()方法,调用start()来启动线程。
new Thread(){ public void run(){ } }.start();
new Thread(new Runnable(){ public voidrun(){ } } ).start();
其实你只需要记住一句话:构造器不是方法,那么用来修饰方法特性的所有修饰符都不能用来修饰构造器(并不等与构造器具备这些特性,虽然不能用static修饰构造器,但它却有静态特性)构造器只能用 public private protected这三个权限修饰符,且不能有返回语句。
子类的构造函数可以通过super关键字显式调用父类中的构造函数。如果子类中的构造函数没有显式调用父类中的构造函数,编译器就会自动在子类的构造函数中调用父类中参数为空的构造函数。
public class Test1{ public static void main(String args[]){ Test1 t = new Test1(); int b = t.get(); System.out.println(b); } public int get(){ try { System.out.println("1111111111"); return 1; } catch (Exception e) { // TODO: handle exception }finally{ System.out.println("222222222222"); return 2; } } }
在JAVA中,是没有类似于PV操作、进程互斥等相关的方法的。JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。
Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程正拥有对象锁,此时主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的锁。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
nofityAll()方法能够唤醒所有正在等待该对象的monitor的线程,这一点与notify()方法是不同的。
这里要注意一点:notify()和notifyAll()方法只是唤醒等待该对象的monitor的线程,并不决定哪个线程能够获取到monitor。
举个简单的例子:假如有三个线程Thread1、Thread2和Thread3都在等待对象objectA的monitor,此时Thread4拥有对象objectA的monitor,当在Thread4中调用objectA.notify()方法之后,Thread1、Thread2和Thread3只有一个能被唤醒。注意,被唤醒不等于立刻就获取了objectA的monitor。假若在Thread4中调用objectA.notifyAll()方法,则Thread1、Thread2和Thread3三个线程都会被唤醒,至于哪个线程接下来能够获取到objectA的monitor就具体依赖于操作系统的调度了。
上面尤其要注意一点,一个线程被唤醒不代表立即获取了对象的monitor,只有等调用完notify()或者notifyAll()并退出synchronized块,释放对象锁后,其余线程才可获得锁执行。
Collection是集合类的一个顶级接口,其直接继承接口有List与Set
而Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。
public class TestJava { public static boolean foo(char c){ System.out.print(c); return true; } public static void main(String[] arg0){ int i=0; for(foo('A');foo('B')&&i<2;foo('C')){ i++; foo('D'); } } }
基本类型、对象的引用储存在stack中;对象储存在heap中。
public class TestJava { public void testFunc(){ //Line 4 } public static void main(String[] arg0){ TestJava t = new TestJava(); //Line 9 } public class Inner{} }
答案:
E