Java基础面试题突击1
文章导读目录
|
JDK
:java development kit (java开发工具),JDK 是用于开发 Java 程序的最小环境。
JRE
:java runtime environment (java运行时环境),是提供给 Java 程序运行的最小环境。
JRE是java运行时环境而JDK是java开发工具包。运行java程序只需安装JRE。如果需要编写java程序,需要安装JDK。但是JRE可以独立安装。
JDK包含JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。
JRE包含了java虚拟机、java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。
二、Java为什么能跨平台?Tip:mac怎么查看jdk目录呢?
终端输入:/usr/libexec/java_home -V会显示jdk版本和所在目录
command + shift +G前往要去的路径
Java是跨平台的原因是因为Java代码是运行在JVM上的,而不是直接运行在操作系统上。
这意味着,Java程序的代码不会直接与操作系统交互,而是通过JVM来间接交互。java是半编译语言,java源程序在经过java编译器编译后成为java字节码文件,再由运行在不同平台上的虚拟机(例如:windows、Linnux)将相同的字节码解释运行,转换成具体平台上的机器指令。从而实现了一次编写,到处运行。
1、Java中数据类型
2、八大基本数据类型
-
整型的byte、short、int、long;
-
字符型的char;
-
浮点型的float、double;
-
布尔型的boolean。
将6种数据类型按取值范围的大小顺序排列一下: double > float > long > int > short > byte
1)数据类型转换
取值范围从小转换到大,是可以直接转换的,
在自动类型转化中、int–> float、long–> float、long–> double、float --> double
可能精度损失外,自动转换不会出现任何运行时异常。而从大转成小,则必须使用强制转换。
2)类型提升
在表达式计算过程中会发生类型转换,这些类型转换就是类型提升,类型提升规则如下:
所有 byte/short/char 的表达式都会被提升为 int
除以上类型,其他类型在表达式中,都会被提升为取值范围大的那个类型,例如有一个操作数为double,整个表达式都会被提升为double
3)基本数据内存中分配
基本数据类型它存放于“栈”中而不是存放于“堆”中。
4)值的初始化
当基本数据类型作为类成员变量时,java 会对其进行初始化。且初始化的值分别为
而局部变量 在没有被显示初始化情况下,jdk 同样也会自动赋予他默认值,可不同之处就在于,你无法引用他,因为编译器会在你要引用的位置报错。
1、异常分类
异常:执行中发生的不正常情况。
Throwable 是 Java 语言中所有错误或异常的超类。下一层分为
Error
和
Exception
Error:JVM系统内部错误、资源耗尽等严重情况。比如Stack OverflowError和 Out Of Memory。
Exception:空指针访问、试图读取不存在的文件、网络连接中断、数组下标越界等。
程序执行过程,是先编译后执行。所以从程序执行的过程可以将异常进一步分为:
编译时异常:执行javac.exe命名时,可能出现的异常
运行时异常:执行java.exe命名时,出现的异常
2、异常的处理方式
1)遇到问题不进行具体处理,而是继续抛给调用者 (throw,throws)
抛出异常有三种形式,一是 throw,一个 throws,还有一种系统自动抛异常。
public static void main(String[] args) {
String s = "abc";
if(s.equals("abc")) {
throw new NumberFormatException();
} else {
System.out.println(s);
}
}
int div(int a,int b) throws Exception{
return a/b;}
2)try catch 捕获异常针对性处理方式
3、Throw 和 throws 的区别
1)位置不同
throws 用在函数上,后面跟的是异常类,可以跟多个;而 throw 用在函数内,后面跟的 是异常对象。
2)功能不同
throws 用来声明异常,让调用者只知道该功能可能出现的问题,可以给出预先的处理方式;throw 抛出具体的问题对象,执行到 throw,功能就已经结束了,跳转到调用者,并将具体的问题对象抛给调用者。也就是说 throw 语句独立存在时,下面不要定义其他语句,因为执行不到。
throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,执行 throw 则一定抛出了某种异常对象。
两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
五、== 和 equals 的区别是什么?
== 对于基本类型:比较的是值是否相同;
对于引用类型:比较的是引用是否相同;
关联知识点:
1、String的比较
String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x== y); // true
System.out.println(x== z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true
原因:String 、Integer 等重写了 Object 的 equals 方法,把引用比较改成了值比较。所以一般情况下 equals 比较的是值是否相等。
2、Integer的比较
Integer a1 = 1;
Integer a2 = 1;
Integer b1 = 128;
Integer b2 = 128;
System.out.println(al== a2); //true
System.out.println(b1== b2); //false
原因:Integer类内部通过静态内部类提供了一个缓存池,范围在-128~127之间,如果超过这个范围 Integer值都是new出来的新对象。
Integer的valueOf方法的具体实现:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
其中IntegerCache类的实现为:
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,
便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
3、两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?
不对。我们两个字符串的哈希值很可能一样,但是反过来不一定成立。
String str1 = "通话";
String str2 = "重地";
System. out. println(String. format("str1:%d | str2:%d", str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));
执行的结果:
str1:1179395 | str2:1179395
false
六、创建对象的几种方法
1、new关键字
使用new关键字创建对象,是最常见也是最简单的创建对象的方式。
2、Class 对象的 newInstance()
使用Class对象的newInstance()方法来创建该 Class 对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空构造器。
3、调用 Constructor 对象的 newInstance()
先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的newInstance()方法来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。
//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//使用.newInstane 方法创建对象
Person p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
//创建对象并设置属性
Person p1=(Person) c.newInstance("测试","男",10);
4、Clone
无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。
5、反序列化
当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象。在反序列化时,JVM创建对象并不会调用任何构造函数。
七、重载和重写1、重写(Override)
从字面上看,重写就是重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,所以在方法名, 参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。
public class Father {
public static void main(String[] args) {
// TODO Auto-generated method stub
Son s = new Son();
s.sayHello();
}
public void sayHello() {
System.out.println("Hello");
}
}
class Son extends Father{
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("hello by ");
}
}
重写总结:
1.发生在父类与子类之间
2.方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同
3.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
4.重写方法一定不能抛出新的检查异常或者比被重写方法明更加宽泛的检查型异常
2、重载(Overload)
在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。
public class Father {
public static void main(String[] args) {
// TODO Auto-generated method stub
Father s = new Father();
s.sayHello();
s.sayHello("wintershii");
}
public void sayHello() {
System.out.println("Hello");
}
public void sayHello(String name) {
System.out.println("Hello" + " " + name);
}
}
八、权限修饰符重载总结:
1.重载Overload是一个类中多态性的一种表现
2.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)
3.重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准
Java规定的4种权限 (从小到大排列) : private、缺省(default)、protected、 public
Java权限修饰符public、protected、default、private置于类的成员定义前,用来限定对象对该类成员的访问权限。
对于class的权限修饰只可以用public和default(缺省)。
public类可以在任意地方被访问。
default类只可以被同一个包内部的类访问。
4种权限可以用来修饰类及类的内部结构: 属性、方法、构造器、内部类
具体的,4种权限都可以用来修饰类的内部结构,属性、方法、构造器、内部类修饰类的话,只能使用default、 public。
九、String、String StringBuffffer 和 StringBuilder 的区别是什么?总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性
String和StringBuffer和StringBuilder的区别 因为String是不可变的,StringBuffer 和 StringBuilder 它们都是可变的字符串。
String是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个fifinal类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生新的String对象。
private final char value[];
StringBuffffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类,他们的底层都是可变的字符数组
/**
* The value is used for character storage.
*/
char[] value;
所以在进行频繁的字符串操作时,建议使用StringBuffffer和StringBuilder来进行操作。
StringBuffffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是
线程安全
;
StringBuilder 并没有对方法进行加同步锁,所以是
非线程安全
的。
1、Collection接口
Collection是集合类的上级接口,子接口有 Set、List、LinkedList、ArrayList、Vector、Stack、 Set;
2、Collections集合类
Collections是集合类的一个帮助类, 它包含有各种有关集合操作的静态多态方法,用于实现对各种集合的搜索、排序、线程安全化等操作。此类不能实例化(因为Collections的构造方法被私有化处理了),就像一个工具类,服务于Java的Collection框架, Collections类中的方法都是被static修饰了,可以直接用类名调用。
Collections类常用方法:
-
public static void shuffle(List)。混乱排序
-
public static boolean addAll(Collection c, T… elements)。添加一些元素
-
public static void sort(List list,Comparator<? super T> )。排序,将集合中元素按照指定规则排序
-
public static <T extends Comparable<? super T>> void sort(List list)。排序,将集合中元素按照默认规则排序
-
public static int binarySearch(List list, Object key)。查找,使用二分搜索法搜索指定的 List 集合,以获得指定对象在 List 集合中的索引。如果要使该方法可以正常工作,则必须保证 List 中的元素已经处于有序状态。
-
public static void copy(List <? super T> dest,List<? extends T> src) 复制, 用于将指定集合中的所有元素复制到另一个集合中。
-
public static void replaceAll()。替换,替换集合中所有的旧元素为新元素。