一. Java基础部分

1、一个".Java"源文件中是否可以包括多个类?有什么限制?
可以包括多个类,但是只能有一个public的类,并且public修饰的类的类名必须与文件名保持一致。
值得注意是的:虽然不是很常用,但编译单元内完全不带public类也是可能的。在这种情况下,可以随意对文件命名。
那么问题来了,如果当java源文件不存在public类时,会出现什么情况? 结果是所以的类都出产生相应的字节码文件,
但是程序所找的入口的和文件名一直的类。
个人总结:
 一个编译单元(java文件)可以存在多个类,在编译时产生多个不同的.class文件,.class文件便是程序运行的数
 据来源。java将public类作为程序的入口,且只能有一个。

2、Java有没有goto?

有的。goto是java保留关键字,但是目前没用使用。
在C语言中goto一般配合条件语句,可用来实现条件转移,形成循环,跳出循环等

3.3、说说&和&&的区别?

&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,
否则,只要有一方为false,则结果为false。

&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如,
对于if(str != null && !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,
所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。
If(x==33 & ++y>0) y会增长, If(x==33 && ++y>0)不会增长

&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,
我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。

作用:提高了逻辑表达式的计算效率.
&&   逻辑与 称为逻辑运算符
&    按位与 称为位运算符
3&5则     
                    0011   
                  &0101     
                    0001   
     等于1

4、在Java中如何跳出当前的多重嵌套循环?

两种方式:
1:可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句;例如
	ok:
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 5; j++) {
                System.out.println("i=" +i);
                System.out.println("j=" +j);
                if (j==4)  break ok;
            }
        }
 2.让外层的循环条件表达式的结果可以受到里层循环体代码的控制.例如
 		 boolean flag = true;
        for (int i = 0; i < 10&&flag; i++) {
            for (int j = 0; j < 5; j++) {
                System.out.println("i=" +i);
                System.out.println("j=" +j);
                if (j==4) {
                    flag = false;
                }
            }
        }

5.switch语句能否作用在byte上;作用在long上;作用在String上?

在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量,整数表达式可以是int基本类型或Integer包装类型
,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。
// switch不可作用于long double float boolean,包括他们的包装类 这些无法转换为int

值得注意的是  在JDK1.7之后,switch可以作用在String上。

6.short s = 1; s = s + 1;有什么错? short s = 1; s += 1;有什么错?

short s = 1 时, s 是short 型的。 s = s + 1 时 ,由于s+1运算时会自动提升表达式的类型为int 型,结果是int型,
	再赋值给short类型s时, int 转换为 short 型 从大变小,会有精度丢失的风险,所以编译器将报告需要强制转换类型的错误。
	short s = 1;
    s = (short) (s +1);
	
	对于short s = 1; s += 1;由于 += 是Java语言规定的运算符,Java编译器会对它进行特殊处理,因此可以正确编译。
	s+=1 相当于:s=(s的数据类型)(s+1);

7、char型变量中能不能存贮一个中文汉字?为什么?

char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。
不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。
补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

8、用最有效率的方法算出2乘以8等於几?

2 << 3,
因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而cpu是直接支持位运算的,效率最高,
所以,2乘以8等於几的最效率的方法是2 << 3。

使用final修饰一个变量时,是引用不能变还是引用的对象不能变?

使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。例如,对于如下语句:
		final StringBuffer a=new StringBuffer("immutable");
		执行如下语句将报告编译期错误:
			a=new StringBuffer("");
		但是,执行如下语句则可以通过编译:
			a.append(" broken!");

10、"=="和equals方法究竟有什么区别?

== 解读

对于基本类型和引用类型 == 的作用效果是不同的,如下所示:
			基本类型:比较的是值是否相同;
			引用类型:比较的是引用是否相同;
 String s1 = "abc";
 String s2 = "abc";
 String s3 = new String("abc");
 System.out.println(s1==s2); // true
 System.out.println(s1==s3); // false
 System.out.println(s1.equals(s2)); // true
 System.out.println(s1.equals(s3)); // true

代码解读:因为 x 和 y 指向的是同一个引用,所以 == 也是 true,而 new String()方法则重写开辟了内存空间,所以 == 结果为 false,而 equals 比较的一直是值,所以结果都为 true。


equals 解读
equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。看下面的代码就明白了。
首先来看默认情况下 equals 比较一个有相同值的对象,代码如下:
class Cat {
    public Cat(String name) {
        this.name = name;
    }
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
Cat c1 = new Cat("王磊");
Cat c2 = new Cat("王磊");
System.out.println(c1.equals(c2)); // false

输出结果出乎我们的意料,竟然是 false?这是怎么回事,看了 equals 源码就知道了,源码如下:

public boolean equals(Object obj) {
		return (this == obj);
}

原来 equals 本质上就是 ==。

那问题来了,两个相同值的 String 对象,为什么返回的是 true?代码如下: 
String s1 = new String("老王");
String s2 = new String("老王");
System.out.println(s1.equals(s2)); // true

同样的,当我们进入 String 的 equals 方法,找到了答案,代码如下:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}


原来是 String 重写了 Object 的 equals 方法,把引用比较改成了值比较。




总结 :== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,
只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
因此这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比
较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。
如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,
那么你必须覆盖equals方法,由你自己写代码来决定在什么情况相等。

http://www.verejava.com/?id=17433712313614 图解