1.&与&&的区别?
&和&&都可以用作逻辑与的运算符,当运算符两边的表达式的结果都为 true 时,整个运算结果才为 true,否则结果为 false。
&&:具有短路的功能,即如果第一个表达式为 false,则不再计算第二个表达式。
&:可以用作位运算符,当&操作符两边的表达式不是 boolean 类型时,&表示按位与操作。
2.在 JAVA 中如何跳出当前的多重嵌套循环?
(1)在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的 break 语句。
(2)外层的循环条件表达式的结果可以受到里层循环体代码的控制。里层循环(break)的结果直接不满足外层循环的条件,即可跳出多重循环。
3.switch 语句的作用类型
在 switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是 int 基本类型或 Integer 包装类型,由于,byte,short,char 都可以隐含转换为 int,所以,这些类型以及这些类型的包装类型也是可以的。long 和 String 类型不能作用于 switch 语句中。
4.char 型变量中能不能存贮一个中文汉字?为什么?
char 型变量是用来存储 Unicode 编码的字符的,unicode 编码字符集中包含了汉字,所以,char 型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在 unicode 编码字符集中,那么,这个 char 型变量中就不能存储这个特殊汉字。补充说明:unicode 编码占用两个字节,以,char 类型的变量也是占用两个字节。
5.用最有效率的方法算出 2 乘以 8 等于几?
2 << 3,因为将一个数左移 n 位,就相当于乘以了2的 n 次方,那么,一个数乘以8只要将其左移3位即可,而位运算 cpu 直接支持的,效率最高。
6.使用 final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
引用变量不能变,引用变量所指向的对象中的内容是可以改变的。
7."=="和 equals 方法究竟有什么区别?
==操作符:专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相同,只能用==操作符。
equals 方法:是用于比较两个独立对象的内容是否相同,字符串的比较基本上都是使用 equals 方法。
如果一个类没有自己定义 equals 方法,那么它将继承 Object 类的 equals 方法,Object 类的 equals 方法的实现代码如下: boolean equals(Object o){ return this==o; } 这说明,如果一个类没有自己定义 equals 方法,它默认的 equals 方法(从 Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals 和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回 false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖 equals方法。
8.静态变量和实例变量的区别?
语法定义上的区别:静态变量前要加 static 关键字,而实例变量前则不加。
程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用,静态变量则可以直接使用类名来引用。
9.是否可以从一个 static 方法内部发出对非 static 方法的调用?
不可以,理由见第8条。
10.Integer 与 int 的区别
int 是 java 提供的8种原始数据类型之一。 Java 为每个原始类型提供了封装类,Integer 是 java为 int 提供的封装类。int 的默认值为0,而 Integer 的默认值为 null,即 Integer 可以区分出未赋值和值为0的区别,int 则无法表达出未赋值的情况。另外, Integer 提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数, Integer中还定义了表示整数的最大值和最小值的常量。
11.Math.ceil()、Math.floor()和Math.round()方法。
Math 类中提供了三个与取整有关的方法:Math.ceil()、Math.floor()和Math.round()
Math.ceil()表示向上取整;Math.floor()表示向下取整;Math.round()表示“四舍五入”,算法为 Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整。
12.作用域 public,private,protected,以及不写时的区别
说明:如果在修饰的元素上面没有写任何访问修饰符,则表示 friendly。
13.Overload 和 Override 的区别
重载 Overload 表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)
重写 Override 表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是 private 类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。
14.构造器 Constructor 是否可被 override?
构造器 Constructor 不能被继承,因此不能重写 Override ,但可以被重载 Overload 。
15.接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?抽象类中是否可以有静态的 main 方法?
接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中可以有静态的 main 方法。抽象类与普通类的唯一区别:就是不能创建实例对象和允许有 abstract 方法。
16.写 clone()方法时,通常都有一行代码,是什么?
clone 有缺省行为, super.clone();因为首先要把父类中的成员复制到位,然后才是复制自己的成员。
17.abstract class 和 interface 有什么区别?
abstract class:abstract 类不能创建的实例对象。含有 abstract方法的类必须定义为 abstract class,abstract class 类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为 abstract类型。
接口(interface):可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为 public abstract 类型,接口中的成员变量类型默认为 public static final。
两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是 public,protected,但接口中的抽象方法只能是 public 类型的,并且默认为 public abstract 类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是 public static final 类型,并且默认为 public static final 类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
18.abstract 的 method 是否可同时是 static?
abstract 的 method 不可以是 static 的,因为抽象的方法是要被子类实现的
19.什么是内部类?
内部类就是在一个类的内部定义的类,内部类中不能定义静态成员,内部类可以直接访问外部类中的成员变量,内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中。
在方法体外面定义的内部类:访问类型可以是 public,protecte,默认的,private 等4种类型,这就好像类中定义的成员变量有4种访问类型一样,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,代码如下: Outer outer = new Outer(); Outer.Inner1 inner1 = outer.new Innner1();
在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用 final 或 abstract 修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加 final 修饰符。
20.String 是最基本的数据类型吗?
基本数据类型包括 byte、int、char、long、float、double、boolean 和 short。 java.lang.String 类是 final 类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用 StringBuffer 类
21.String 和 StringBuffer 的区别
JAVA 平台提供了两个类:String 和 StringBuffer,它们可以储存和操作字符串,String 类提供了数值不可改变的字符串。而 StringBuffer 类提供的字符串进行修改。当知道字符数据要改变的时候就可以使用 StringBuffer来动态构造字符数据。另外,String 实现了 equals 方法,newString(“abc”).equals(newString(“abc”)的结果为 true,而 StringBuffer 没有实现 equals 法,所以,new StringBuffer(“abc”).equals(newStringBuffer(“abc”)的结果为 false。String 覆盖了 equals 方法和 hashCode 方法,而 StringBuffer 没有覆盖 equals 方法和hashCode 方法,所以,将 StringBuffer 对象存储进 Java 集合类中时会出现问题。
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况,线程不安全的
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况,线程安全的
22.数组有没有 length()这个方法? String 有没有 length()这个方法?
数组没有 length()这个方法,有 length 的属性。String 有有 length()这个方法。
23.Java 中的异常处理机制的简单原理和应用
异常是指 java 程序运行时(非编译)所发生的非正常情况或错误,Java 对异常进行了分类,不同类型的异常分别用不同的 Java 类表示,所有异常的根类为java.lang.Throwable,Throwable 下面又派生了两个子类:Error 和 Exception,Error 表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。Exception 表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。编译器强制普通异常必须 try..catch 处理或用 throws 声明继续抛给上层调用方法处理,所以普通异常也称为 checked 异常,而系统异常可以处理也可以不处理,所以,编译器不强制用 try..catch 处理或用 throws 声明,所以系统异常也称为 unchecked 异常。
24.sleep()和 wait()有什么区别?
sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用 sleep 不会释放对象锁。 wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出 notify 方法(或 notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
sleep 就是正在执行的线程主动让出 cpu,cpu 去执行其他线程,在 sleep 指定的时间过后,cpu 才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep 方法并不会释放锁,即使当前线程使用 sleep 方法让出了 cpu,但其他被同步锁挡住了的线程也无法得到执行。wait 是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了 notify 方法(notify 并不释放锁,只是告诉调用过 wait 方法的线程可以去参与获得锁的竞争了。
25.同步和异步有何异同,在什么情况下分别使用他们?
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
26.启动一个线程是用 run()还是 start()?
启动一个线程是调用 start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。
27.synchronized 和 java.util.concurrent.locks.Lock 的异同?
主要相同点:Lock 能完成 synchronized 所实现的所有功能
主要不同点:Lock 有比 synchronized 更精确的线程语义和更好的性能。synchronized 会自动释放锁,而 Lock 一定要求程序员手工释放,并且必须在 finally 从句中释放。Lock 还有更强大的功能,例如,它的 tryLock 方法可以非阻塞方式去拿锁。
28.Collection和Map 框架的结构
Collection有两个子接口:List 、Set
List三个实现类: ArrayList 的底层是数组,查询快,增删慢;LinkedList 的底层是双向链表,增删快,查询慢;Vector 的底层是数组,线程安全的。
Set有一个实现类HashSet以及一个子接口(SortedSet)。SortedSet有一个实现类TreeSet,底层实现是二叉树,实现了Comparable接口,按元素大小自动排序。
Map有两个实现类HashMap、HashTable,以及一个子接口SortedMap。SortedMap有一个实现类TreeMap。
29.ArrayList 和 Vector 的区别
这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是确定的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,并且其中的数据是允许重复的。
同步性:Vector 是线程安全的,也就是说是它的方法之间是线程同步的,而 ArrayList 是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
数据增长:ArrayList 与 Vector 都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加 ArrayList 与 Vector 的存储空间,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector 默认增长为原来两倍,而 ArrayList 的增长为原来的1.5倍。ArrayList 与 Vector 都可以设置初始的空间大小,Vector 还可以设置增长的空间大小,而 ArrayList 没有提供设置增长空间的方法。
30.HashMap 和 Hashtable 的区别
HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,主要区别在于 HashMap 允许空(null)键值(key)。Hashtable 的方法是 Synchronize 的,而 HashMap 不是,在多个线程访问Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为之提供外同步,由于非线程安全,在只有一个线程访问的情况下,效率要高于 Hashtable。
31.Collection 和 Collections 的区别
Collection 是集合类的上级接口,继承与他的接口主要有 Set 和 List。Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
32.序列化接口Serializable
要将 java 对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个 java 对象变成某个格式的字节流再传输,jre 本身就提供了这种支持,我们可以调用OutputStream 的 writeObject 方法来做,如果要让 java 帮我们做,要被传输的对象必须实现 serializable 接口,这样,javac 编译时就会进行特殊处理,编译的类才可以被 writeObject 方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable 接口,该接口是一个 mini 接口,其中没有需要实现的方法,implements Serializable 只是为了标注该对象是可被序列化的。
33.assert
assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion 就是在程序中的一条语句,它对一个 boolean 表达式进行检查,一个正确程序必须保证这个 boolean 表达式的值为 true;如果该值为 false,说明程序已经处于不正确的状态下,assert 将给出警告或退出。一般来说,assertion 用于保证程序最基本、关键的正确性。assertion 检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion 检查通常是关闭的。