1、String s=new String("abc")
为了方便理解,可以将上述语句的执行 分解成两个过程 ,第一个过程是新建对象 的过程,即new String("abc");第二个过程是赋值的过程,即String s=。由于第二个过程只是定义了一个名为s的String类型的变量,将一个String类型对象的引用赋给s,因此这个过程不会创建新的对象。第一个过程new String("abc")会调用String类的构造函数:
public String (String str){
//body
}
在调用这个构造函数时,传入了一个字符串常量,因此语句new String("abc")也就等价于"abc"和new String()两个操作了。若在字符串池中不存在"abc",则会创建一个字符串常量"abc",并将其添加到字符串池中;若存在,则不创建。而new String()会在堆中创建一个新的对象 。
2、Class.forName和ClassLoader的区别
在Java中,类(class)只有被加载到jvm中后才能运行,当运行指定程序时,jvm会将编译生成的.class文件按照一定规则加载到内存中,并组织成为一个完整的Java应用程序。这个过程是由ClassLoader和它的子类完成的。
ClassLoader是通过委托的方式实现类加载的。当有类需要被加载时,类加载器会请求父类来完成这个载入工作,父类会使用其自己的搜索路径来搜索需要被载入的类,如果搜索不到,才会由子类按照其搜索路径来搜索待加载的类。
先看一下Class.forName的源码
forName0方法的第二个参数表示是否初始化,为true意味者对静态变量和静态代码块执行初始化工作。
所以说Class.forName()除了对类进行加载,还会对静态变量和静态代码块进行初始化。当然也可以用另一个重载方法来手动决定是否对静态变量和静态代码块进行初始化。
总结:类加载主要步骤为 以下3步:
1)装载。根据查找路径找到对应的class文件,然后导入
2)链接。分为三步:
①检查 。检查待加载的class文件的正确性
②准备。给类中的静态变量分配存储空间
③解析。将符号引用转换成直接引用(可选)
3)初始化。对静态变量和静态代码块执行初始化工作
3、什么是Java序列化,什么情况下使用?
序列化是一种 将对象以一连串的字节描述的过程。序列化可以将对象的状态写在流里ji进行网络传输,或者保存到文件、数据库等系统里。
所有要实现序列化的类都必须实现Serializable接口,它里面没有任何方法。使用一个输出流(例如FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,然后调用该对象的writeObject(obj)就可以将对象序列化。要反序列时调用相应的输入流即可。
4、finally块中的代码什么时候被执行
public class Test{
public static int test(){
try{
return 1;
}catch(Exception e){
return 0;
}finally{
System.out.println("abc");
}
}
public static void main(String [] args){
System.out.println(test());
}
}
结果是:
abc
1
在Java语言的异常处理中,finally块的作用是为了保证无论出现什么情况,finally块里的代码一定会被执行。由于 程序执行return就意味这结束对当前函数的调用并跳出这个函数体,因此任何语句要执行都要在return前执行(除非碰到exit函数),因此finally块里的代码也是在return前执行的。
当finally块中有return语句时,将会覆盖函数中其他return语句。
5、Thread的sleep()方法与Object的wait()方法有何不同?
1)原理不同: sleep()方法是Thread类的静态方法,是线程用来控制自身流程的,它会使此线程暂停执行一段时间,等到计时时间一到,此线程会自动"苏醒"。Object的wait()方法,用于线程间的通信,这个方法会使当前拥有该对象锁的进程等待,直到其他线程调用notify()方法或notifyAll方法才会"苏醒",也可以给它指定一个时间,自动"醒来"
2)对锁的处理机制不同 : sleep()方法主要作用让线程暂停一段时间,时间一到自动恢复,不涉及线程间的通信,因此调用sleep()方法并不会释放锁。而wait()方法不同,当调用wait()方法后,线程会释放掉它所占用的锁,从而使线程所在对象中的其他synchronized数据可被别的线程使用
3)是否会抛异常: sleep()会抛出异常,wait()不会
6、一个数如果恰好等于它的因子之和,这个数就称为 "完数 "。例如6=1+2+3.编程 找出1000以内的所有完数。
public class Wanshu {
public static void main(String[] args) {
System.out.println(getWanshu(1000));
}
public static List<Integer> getWanshu(int num) {
List<Integer> list = new ArrayList();
for (int i = 1; i <= num; i++) {
int temp = 0;
for (int j = 1; j < i; j++) {
if (i % j == 0) {
temp += j;
}
}
if (i == temp) {
list.add(i);
}
}
return list;
}
}
7、什么是IOC,什么是AOP?
IOC控制反转,有时也会被称为依赖注入,是一种降低对象之间耦合关系的设计思想。一般而言,在分层体系结构中,都是上层调用下层的接口,上层依赖于下层的执行,即调用者依赖于被调用。而通过IOC方式,使得上层不再依赖于下层的接口,即通过采用一定的机制来选择不同的下层实现,完成控制反转。IOC通过注入一个实例化的对象来达到解耦的目的。spring如何依赖注入的?是通过反射机制来实现的。
AOP面向切面编程,是对面向对象开发的一种补充,它允许开发人员在不改变原来模型上动态的修改模型以满足新的需求。例如不改变原来业务逻辑模型的基础上可以动态的增加日志、安全或异常处理的功能。本质上使用的是动态代理。
8、数据库
select 教师号,
sum(case when 星期号=1 and 是否有课=’有’ then 1 else 0 end) AS 星期一,
sum(case when 星期号=2 and 是否有课=’有’ then 1 else 0 end) AS 星期二,
sum(case when 星期号=3 and 是否有课=’有’ then 1 else 0 end) AS 星期三
from teacher_course
group by 教师号
9、二分法
1)先来看下数学中是怎么定义的:
对于区间[a,b]上连续不断且f(a)·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法
2)二分法查找就是给定一个数,让你在一堆数据中查找。二分法查找适用于数据量较大时,但是数据需要先排好顺序。主要思想是:(设查找的数组区间为array[low, high])。具体如下:
(1)确定该区间的中间位置K
(2)将查找的值T与array[k]比较。若相等,查找成功返回此位置;否则确定新的查找区域,继续二分查找。区域确定如下:a.array[k]>T 由数组的有序性可知array[k,k+1,……,high]>T;故新的区间为array[low,……,K-1]b.array[k]<T 类似上面查找区间为array[k+1,……,high]。每一次查找与中间值比较,可以确定是否查找成功,不成功当前查找区间将缩小一半,递归查找即可。时间复杂度为:O(log2n)。
3)实现
public class BinaryTest
{
public static int binary(int[] array, int value)
{
int low = 0;
int high = array.length - 1;
while(low <= high)
{
int middle = (low + high) / 2;
if(value == array[middle])
{
return middle;
}
if(value > array[middle])
{
low = middle + 1;
}
if(value < array[middle])
{
high = middle - 1;
}
}
return -1;
}
public static void main(String[] args)
{
int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int value = binary(a, 9);
System.out.println(value);
}
}