Java基础

77 阅读7分钟

1 为什么Java被称作是与平台无关的编程语言

java跨平台是指在不同的平台安装不同的JVM,字节码文件由JVM解释成对应平台的机器码。

2 理解JDK,JRE,JVM

  • JDK:Java开发工具包,包括JRE,还有一些小工具如javac.exe
  • JRE:Java运行环境,JVM实现(jre/bin/server/jvm.dll)+java基本类库(rt.jar等)
  • JVM:Java虚拟机,执行.class文件,是Java支持跨平台的关键

3 JDK各个版本的新特性

  • JDK5 自动装箱拆箱 增强for循环 静态导入 可变参数 枚举 线程并发库JUC 注解

  • JDK7

    • 二进制字面值,int a=0b1001
    • switch支持String类型,反编译可以看到其原理是 - 根据str的hashcode来匹配,如果为null会报空指针异常
    • try-with-resources
    • catch 多个类型异常
    • 字面值中使用下划线
    • 类型推断
  • JDK8

    • lambda表达式
    • 函数接口
    • StreamAPI
    • 新的日期时间API:LocalDate、LocalTime 和 LocalDateTime类
    • optional类
    • 增强类型推断
    • 方法引用等,如类::实例方法
    • 接口支持默认方法,静态方法
  • JDK9

    • 目录结构:JDK目录结构有变化,其中去掉了jre目录
    • 模块化系统
    • 接口的私有方法
    • 改进try-with-resources
    • String存储结构变化,由char[]变为byte[]

参考www.cnblogs.com/peter1018/p…

4 int和Integer

int和Integer的区别

  • 数据类型不一样,int是基础数据类型,Integer是包装数据类型
  • 默认值不一样,int初始值是0,Integer初始值是null
  • 存储方式不一样,int存储在栈中,Integer存储在堆中
  • Integer是对象类型,封装了很多方法,使用更灵活
  • 泛型只能使用Integer

int和Integer使用场景

  • 整数运算使用int,加减乘除运管比较多
  • 高精度运算使用Integer
  • 集合元素用Integer
  • 泛型使用int

5 java中四种修饰符的限制范围

  • public所有类
  • default包
  • protect子类
  • private本类

6 接口和抽象类的区别,注意JDK8的接口可以有实现。

  • 接口支持多实现,抽象类只能单继承
  • 实现接口时,必须实现所有方法,继承抽象类,不需要实现所有方法,可以定义成抽象的
  • 接口中的实例变量默认是static final

7 值传递和引用传递的区别。

  • 值传递,传递的是值的副本,不会影响原值,基本类型是值传递
  • 引用传递,传递的是对象的引用,两个引用指向的是同一个对象,改变引用的实体将改变原实体的值,引用类型都是引用传递

8 为什么重写equals方法时必须重写hashcode方法

object规范的约定内容如下:

两个对象根据equals方法比较相等,其hashcode必须相等。 两个对象不相等,其hashcode不要求一定不相同,但我们应该知道,给不同的对象生成截然不同的hashcode值,有可能提供哈希表的效率。

9 泛型

泛型在编译时强化元素类型信息,并在运行时擦除。有了泛型之后,编译时就可以知道是否插入了类型错误的对象。

List为原生类型,原生类型的存在是为了兼容Java5之前的代码,是不安全的,在Java5之后尽量使用泛型 List<Object>表示可以包含任何对象类型的集合 List<?>表示只能包含某种未知对象类型的集合,为无限制通配类型

举例说明List、List<Object>和List<?>的区别

  • List可以接收List类型的参数,运行时可能报错,使用原生类型失去了类型安全性
  • List不能接收List类型的参数,编译时报错
  • List不能将任何元素(除了null)放到List中,编译时报错
  • 	public static void main(String[] args) {
    		List<String> list = new ArrayList<String>();
    		addofPrototypeList(list, new Integer(10));
    		String str = list.get(0);//运行时报类型转换错误
    		addofObjectList(list, new Integer(10));//编译时报错		
    		add(list, new Integer(10));		
    	}
    
    	private static void addofPrototypeList(List list, Object o) {
    		list.add(o);
    	}
    	
    	private static void addofObjectList(List<Object> list, Object o) {
    		list.add(o);
    	}
    	
    	private static void add(List<?> list, Object o) {
    		list.add(o);//编译时报错
    	}
    

    10 static

    • 静态变量被所有的对象所共享,在类初次加载时会被初始化,在内存中只有一个副本,。
    • 非静态变量在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

    11 this逃逸

    • 含义:对象没有构造完成,对象的this引用就被发布出去了。
    • 产生条件:在构造函数中创建并发布了内部类。
    • 举例:在一个类的构造器创建了一个内部类(内部类拥有对外部类所有成员的访问权),此时外部类的成员变量还没初始化完成,但内部类被其他线程获取到,并调用了内部类访问到外部类未初始化的成员变量的方法。
    • www.cnblogs.com/straybirds/…

    12 代码加载顺序

    父类

    public class Father {	
    	public Father(){
    		System.out.println("4 父类静态构造函数");
    	}
    	
    	{
    		System.out.println("3 父类静态构造代码块");
    	}
    	
    	static{
    		System.out.println("1 父类静态代码块");
    	}
    }
    

    子类

    public class Son extends Father{
    	public Son(){
    		System.out.println("6 子类静态构造函数");
    	}
    	
    	{
    		System.out.println("5 子类静态构造代码块");
    	}
    	
    	static{
    		System.out.println("2 子类静态代码块");
    	}
    	
    	public static void main(String[] args) {
    		System.out.println("main 开始...");
    		new Son();
    		new Son();
    		System.out.println("main 结束");
    	}
    }
    

    输出结果
    1 父类静态代码块
    2 子类静态代码块
    main 开始...
    3 父类静态构造代码块
    4 父类静态构造函数
    5 子类静态构造代码块
    6 子类静态构造函数
    3 父类静态构造代码块
    4 父类静态构造函数
    5 子类静态构造代码块
    6 子类静态构造函数
    main 结束

    总结

    • 在主类中定义的静态块,优先于主方法(main)执行
    • 静态块优先于构造块执行。无论产生多少实例化对象,静态块都只执行一次。
    • 构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块,构造块可以进行简单的逻辑操作
    • 有继承关系的话,在main方法里 new 子类,则先调父类,再调子类

    13 finally和return执行问题

    • 不管有没有出现异常,finally块中代码都会执行;
    • 当try和catch中有return时,finally仍然会执行;如下:
    	try{
    		return; 
    	}catch(){
    	
    	}finally{
    	
    	} 
    	return;
    
    
    • 程序执行try块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,最后执行try中return; finally块之后的语句return,因为程序在try中已经return所以不再执行。

    • finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来, 不管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;

    • finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

    14 内部类

    • 成员内部类 成员内部类,可以访问外部类的所有成员 内部类不允许定义静态变量
    • 局部内部类(方法内定义) 可以访问当前代码块内的常量,和此外围类所有的成员。 局部内部类访问它所在方法的局部变量时,要求该局部变量必须声明为final的原因 (原因:局部内部类对象的生命周期比局部变量的生命周期长) 局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
    • 静态内部类 要创建内部类的对象,并不需要其外部类的对象。 不能访问外部类的非静态对象。
    • 匿名内部类 www.cnblogs.com/ldl326308/p…

    15 深拷贝、浅拷贝

    • 深拷贝:目标对象和原对象是独立的,不会互相影响
    • 浅拷贝:
      • 值类型:拷贝对象的值
      • 引用类型,拷贝对象的地址,修改目标对象会改变原对象的值

    16 异常类

    • Throwable:Error和Exception(包括-RuntimeException)
    • 可查异常:Exception中除RuntimeException的异常,必需处理,捕获或抛出
    • 不可查异常:Error和RuntimeException,可以处理也可以不处理
    • 运行时异常:runtimeException

    17 创建对象的方法

    • 用new语句创建对象
    • 运用反射手段,调用java.lang.Class 或者 java.lang.reflect.Constructor 类的newInstance()实例方法
    • 调用对象的clone()方法
    • 运用序列化手段,调用java.io.ObjectInputStream 对象的 readObject()方法(对象的反序列化,对象输入流)