一、Java基础
1、什么是面向对象
面向对象是一种编程风格,把一切东西看成是一个个对象。面向对象具有封装、继承、多态等特性。更易维护、易扩展、易复用。
- 封装:封装是将对象属性私有化,同时提供一些可以被外部访问属性的方法,内部细节对外部调用透明,外部只需要调用而不用管具体是怎么实现。有效实现了对数据和行为的包装和信息隐藏。
- 继承:继承描述的是多个类之间的所属关系,子类拥有父类的属性和方法(包括私有属性和私有方法,但是私有属性和方法子类无法方位,只是拥有),也可以拥有自己的属性和方法(对父类进行扩展)或用自己的方式实现父类方法(重写)。继承可以方便的复用以前的代码。
- 多态是指不同事物具有不同表现形式的能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。一个接口,多种实现方式。
2、JVM、JDK和JRE
- JVM:Java虚拟机,是运行Java字节码的虚拟机。是Java语言“一次编译,随处运行”的关键。
- JDK:Java开发工具包,包括JRE、编译器(javac)和工具(javadoc、jdb等)。能够创建和编译程序。
- JRE:Java运行时环境,包含运行已编译Java程序所需所有内容的集和,包括JVM、Java类库、java命令和其它基础构件。不能用于创建新程序。
3、String、StringBuffer和StringBuilder
- 1、可变性 —— String是不可变的,StringBuffer和StringBuilder是可变的
String类中使用final关键字修饰字符数组保存字符串(private final char value[]),所以String对象是不可变的。而StringBuffer和StringBuilder继承自AbstractStringBuilder类,使用字符串数组char[]value,没有用final关键字修饰,所以是可变的。 - 线程安全性——String和StringBuffer是线程安全的,StringBuilder是非线程安全的。
String对象是不可变的,所以是线程安全的。StringBuffer对方法(如expandCapacity、append、insert、indexOf)加了同步锁而StringBuilder没有,所以StringBuffer是线程安全的,StringBuilder是非线程安全的。 - 性能——SpringBuilder>StringBuffer>String
因为String是不可变的,每次对String类型改变时都会生成一个新的String对象,然后将指针指向新的String对象,所以性能低。而StringBuffer和StringBuilder对本身进行操作,但是StringBuild需要保证线程安全所以效率比StringBuffer低。
三者总结: - 操作少量数据:String
- 单线程操作大量数据:StringBuilder
- 多线程操作大量数据: StringBuffer
4、包装类、自动装箱和拆箱
为什么有包装类?
Java是一种面向对象的编程语言。一切皆对象。对象内部可以封装一系列属性和行为,但是基本类型是不具备Java中对象的某些特征,所以对应的包装类型就应运而生了。
- 装箱:将基本类型用对应的引用类型包装起来;
- 拆箱:将包装类型转换为基本数据类型。
int装箱的时候自动调用Integer的valueOf(int)方法;Integer拆箱的时候自动调用Integer的intValue方法。
5、接口和抽象类的区别
抽象类
在Java中被abstract关键字修饰的类称为抽象类,用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。
接口
Java中接口使用interface关键字修饰。接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。接口只是一种形式,接口自身不能做任何事情。接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误)
区别
接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
从使用方式上来说,二者有如下的区别:
接口里只能包含抽象方法、静态方法、默认方法和私有方法,不能为普通方法提供方法实现;抽象类则完全可以包含普通方法。
接口里只能定义静态常量,不能定义普通成员变量;抽象类里则既可以定义普通成员变量,也可以定义静态常量。
接口里不包含构造器;抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
接口里不能包含初始化块;但抽象类则完全可以包含初始化块。
一个类最多只能有一个直接父类,包括抽象类;但一个类可以直接实现多个接口,通过实现多个接口可以弥补Java单继承的不足。允许一个类遵循多个特定的接口。如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。
接口和抽象类很像,它们都具有如下共同的特征:
接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。
接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。
6、==与equels
== :判断两个对象地址是否相等。即判断两个对象是不是同一对象(如果是基本数据类型 == 比较的是值,引用数据类型==比较的是地址)。
equels():equals()方法在没有重写时等价于“ == ”,但我们通常的需求是,若两个不同的对象它们的内容是相同的,就认为它们相等。所以通常都要重写equals()方法。
public class test{
public static void main(String[] args){
String a=new String("ab");
String b=new String("ab");
String aa="ab";
String bb="ab";
if(aa == bb) //true
if(a == b) //false
if(a.equals(b)) //true String中equals方法被重写过
}
}
7、hashCode()和为什么要有hashCode?
hashCode()用于获取哈希码,来确定对象在哈希表中的索引位置。能根据“键”快速检索出对应的“值”。
用途:HashSet检查重复:首先计算对象的hashcode判断对象加入的位置,如果没有找到则假设对象没有重复出现,若找到有相同hashcode值的对象,会调用equals()方法检查对象是否相等,如果相同就不会添加。通过hashCode()可以大大减少equals的比较次数,提升效率。
8、hashCode() 和equals()
hashCode()用于获取散列码,eauqls()用于比较两个对象是否相等,但是它们应遵守如下规定:
- 对象相等,则必须有相同的哈希码。
- 对象有相同的哈希码,对象不一定相等。
9、为什么要重写equals()和hashCode()?
Object类提供的equals()方法默认是用==来进行比较的,也就是说只有两个对象是同一个对象时,才能返回相等的结果。但我们通常的需求是,若两个不同的对象它们的内容是相同的,就认为它们相等。Object类中equals()方法的默认实现是没有实用价值的,所以通常都要重写。而为了保证上面 hashCode() 和equals()的关系,需要重写hashCode()。
10、final关键字
- 对于一个final变量,如果是基本数据类型变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再指向其它对象。
- 当final修饰一个类,表明这个类不能被继承,并且final类中所有的成员方法都会被隐式的指定为final方法。
11、异常处理
- try块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
- catch块:用于处理try捕获到的异常。
- finally块:无论是否捕获或处理异常,finally块里的语句都会执行。当在try块或catch块中遇到return语句时,finally块将在方法返回之前被执行。
finally块不会被执行的情况:
- 1、finally块中第一行发生了异常。
- 2、前面代码使用了System.exit(int)退出程序。
- 3、程序所在的线程死亡
public static int f(int a){
try{
return a;
}finally{
if(a==2){
return 0;
}
}
}
f(2) //返回值为0 finally块返回值覆盖try返回值
12、Java获取键盘输入的方法
- 1:通过Scanner
Scanner input =new Scanner(System.in);
String s = input.nextLine();
input.close();
- 2:通过BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s=input.readLine();