Java回顾2【笔记】
String前言
通过六个题目彻底掌握String笔试面试题
String x = "abc";
String y = new String("abcd");

注意:new 出来的堆中的对象也是指向常量池的,存的是地址
Java中String对象在堆和常量池中的情况及比较
0. ==比较地址,equals被重写后是比较内容
1. 内部类
--成员内部类
------ --静态内部类
------ --非静态内部类
--局部内部类(在方法体内的)
------ --匿名内部类
------ --局部内部类
static class Inner{} 内部和正常类一样,可以存在静态与非静态
但他仍得遵循静态的原则,不能使用外部类的非静态成员
外部类中使用他,正常调用,例如类名.静态,对象名.非静态
外部类外使用他,例如Outer.Inner in = new Outer.Inner();就是在基础上多加一个外部类的名字
class Inner{} 内部不能出现任何和static有关声明
可以随意使用外部的成员,因为这个类不是静态的,所以外部的静态方法不能调用他
外部类中使用他,应该是正常调用
外部类外使用他,巨奇葩,先创建外部对象Outer out = new Outer();
再Outer.Inner in = out.new Inner();
new Person(){ public void shout(){System.out.println("***u!");} }.shout();
直接重写Person的方法并且调用
局部内部类,算了,估计也用不到,浪费脑容量。修饰符只能有abstract或final...
2. 枚举
public enum Season{SPRING, SUMMER, AUTUMN, WINTER; private Season(){}} 默认继承了java.lang.Enum
实际上,前面四个季节相当于public static final Season SPRING = new Season();
也就是说,枚举就是先帮你创建好几个单例对象,供你使用
所以SPRING("春天")这样是可以的,只要你写一个构造函数即可,也可以重写toString()
3. 注解
public @interface Person{ String value() default "人";} 注解中只有属性,default可加可不加
不太理解,注解有啥用?我写了个value,但注解在方法上以后又有什么效果呢?
明白了,注解只是设置一下属性,然后需要通过反射去获取注解的属性。要结合!!!反射!!!使用才有用
系统预定义的三个注解:@Override @SuppressWarnings @Deprecated(过时)
文档注释注解:@author @see @since...
元注解:注解的注解
@Target:位置
@Rentention:滞留阶段
@Documented:是否读取到API
@Inherited:是否被子类继承
4. 异常Throwable
--Error(严重错误,不需要catch)
--Exception
------- --RuntimeException or 子类 NullPointerException ClassCastException IndexOutOfBoundsException
------- --编译时异常:FileNotFoundException IOException SQLException
解决方法:
运行时异常throw new NullPointerException("空指针异常!")
编译时异常throws/try catch,抛出或者catch
运行时异常不需要写在try catch里,例如if else里即可。
可以自己写一个类继承RuntimeException,然后写带msg参数的构造方法,再重写getMessage()方法
如果用的是自定义的异常,会要求你抛出,抛出后再被catch到,e.getMessage()。如果不重写getMessage()方法的话就不会显示内容。
当出现return 和 finally。return之前,必定会走一遍finally。
5. 包装类 自动拆/装箱 缓存对象 Byte,Short,Integer,Long都有-128~127; Character为0~127,在这个缓存范围中,他们仍存储在栈中。
Integer.parseInt(String s)
Integer.toBinaryString()
.toOctalString()
.toHexString()
MAX_VALUE/MIN_VALUE
Character.toUpperCase('a')
.toLowerCase('A')
补充:
6. Date SimpleDateFormat Calendar
7. 泛型 来告知这个瓶子里要装什么东西,泛型必须得是引用数据类型
泛型类:
public class ArrayList<E>{}
泛型方法:
public <T> void test(){} 不知道有啥意义
未设定泛型,泛型被擦除会解析为泛型形参的第一个上限的类型,若没有extends就为Object 例如<T extends Number & Comparable>
8. 单例
public class Lazy(){
private Lazy(){}
private static class Inner{
public static final Lazy INSTANCE = new Lazy();
}
public static Lazy getInstance(){
return Inner.Instance;
}
}
9. String
其对象不可变,只要修改字符串就会产生新的对象,新对象会放在常量池中
常量池在哪?JDK1.6方法区,JDK1.7堆,JDK1.8元空间
String对象底层的存储,private final char[],JDK1.9 private final byte[]
对象题
第一题:String s = new String("hello");//创建了几个对象
第二题:
String s1 = new String("world");
String s2 = new String("world");//创建了几个对象
第一题为2个,new String()在堆中创建了一个对象存储world,world在常量池创建了一个对象
第二题为3个,两个new String()创建了两个,world重复了,只创建了一个
地址题
常量+常量->常量池
常量+变量->堆
s.intern()->常量池
我自己的理解可能有误,例如name="L",此时我的name指向的是常量池的,所以拿name去==比较时他是常量池的
而我把name作为变量与其他String相加的时候,它就是作为变量相加,所以相加后的结果就为堆
作为形参
String作为形参传入方法,并修改值,不会对实参造成影响
而普通对象作为形参传入方法,利用set方法,会对实参造成影响,为什么呢?
详细解释在Java回顾1的底下的题目那一块有说明。在此粗略解释:
因为其实实参和形参的传递仅仅只是一次赋值而已,就是给形参赋了值,他们俩之间并没有其他关系。这样明白了么
包装类题目:
Integer i = 1;
Integer j = 1;
System.out.println(i == j);//true
Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false
Integer i = new Integer(1);//新new的在堆中
Integer j = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(i == j);//false
Integer i = new Integer(1);//新new的在堆中
Integer j = new Integer(1);//另一个新new的在堆中
System.out.println(i == j);//false
Integer i = new Integer(1);
int j = 1;
System.out.println(i == j);//true,凡是和基本数据类型比较,都会先拆箱,按照基本数据类型的规则比较
String题目:
@Test
public void test06(){
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = (s1 + "world").intern();//把拼接的结果放到常量池中
String s5 = (s1 + s2).intern();
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//true
}
@Test
public void test05(){
final String s1 = "hello";
final String s2 = "world";
String s3 = "helloworld";
String s4 = s1 + "world";//s4字符串内容也helloworld,s1是常量,"world"常量,常量+ 常量 结果在常量池中
String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是常量,常量+ 常量 结果在常量池中
String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//true
System.out.println(s3 == s6);//true
}
@Test
public void test04(){
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1 + "world";//s4字符串内容也helloworld,s1是变量,"world"常量,变量 + 常量的结果在堆中
String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是变量,变量 + 变量的结果在堆中
String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
System.out.println(s3 == s4);//false
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//true
}
/*--------------------------4-----------------------------*/
public static void main(String[] args) {
String ab = "ab";
final String b = getBB();
String ab2 = "a" + b;
System.out.println(ab == ab2);//!!!!!!!!!!false,因为getBB就是堆中的,即便定义为final他也不是常量
}
private static String getBB() {
return "b";
}
陌生所以绝对重要:
集合底层/多线程(锁)/反射/IO
序列化/类加载过程...
1.8新特性/网络
知识离开了脑子,就只是一堆文字

浙公网安备 33010602011771号