目录
为什么集合类没有实现Cloneable和Serializable接口?
String、StringBuffer、StringBuilder区别
你是如何调用 wait()方法的?使用 if 块还是循环?为什么?
ArrayList、LinkedList、Vector的区别
持续ing.....
Java语言基础部分
JVM?JDK?JRE?
JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心。
JRE :英文名称(Java Runtime Environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
Java语言的特点
面向对象
跨平台解释执行,一次编译到处执行
健壮性和安全性:编译运行过程中提示错误
支持多线程
Java语言的特性
封装
继承
多态:方法重载、方法覆盖
抽象
基本数据类型
byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。
char:16位,存储Unicode码,用单引号赋值。
short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。
int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正 的2的31次方减1。
long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正 的2的63次方减1。
float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
boolean:只有true和false两个取值。
byte常用在什么地方
读取文件时(如图片,声音,可执行文件)需要用字节数组来保存文件的内容
int n = 0;
try {
FileInputStream fis = new FileInputStream("f:\\files\\1.txt");
FileOutputStream fos = new FileOutputStream("f:\\files\\copy.txt");
byte[] bs = new byte[1024*1024];
while ((n = fis.read(bs)) != -1) {
fos.write(bs,0,n);
}
fis.close();fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
数据输入
1.BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String str[] = bf.readLine().split(" ");//读取一行输入用“ ”分割开。
2.Scanner sc = new Scanner(System.in);
常用Math方法(静态)
int abs(int i) 求绝对值
int max(int i, int j)
double ceil(double d) 向上取整
double floor(double d) 向下取整
double sqrt(double d) 开平方
int round(float f) 靠近 f 的整数
double.random() 返回[0,1)之间的一个随机数
switch语句
switch( x ){
case 0:
case 1:
...
}
跳转语句 break和continue
1.Break:跳出当前循环体
2跳出多重循环:
out:
for(...){
for(...){
break out;
}
}
3.continue: 终止此次循环,继续下一次,不跳出循环体
如何在main()方法之前输出”Hello World”?
用 static 块输出
java中的 clone()方法作用?
复制对象,修改新的对象原对象不变
浅复制和深复制的区别?
对于基本类型来说一样,对于引用类型才有区别
浅复制只是复制了引用,不复制引用所指向的对象
深复制即复制引用,也复制指向的对象
Java反射机制
得到一个对象的类,可以获取类的方法和属性的一种机制;运行时创建对象,运行时调用对象的方法
常用方法:
//getMethods方法获得所有public的方法,包括继承而来
Method[] ms = c.getMethods();
//getDeclaredMethods是获取该类自己的声明的方法
Method[] ms = c.getMethods();
//获取类中属性
Field[] fs = c.getDeclaredFields();
Constructor[] cs = c.getConstructors();
获取类:
- Class.forName(“包.类名”);
- 类名.Class;
- 实例.getClass();
创建对象的方式:
- new语句实例化对象
- 反射机制创建对象
- Clone方法创建对象
- 反序列方法创建对象
什么是String不可变
String s = “hello”;
s = “word”;
String 的引用对象 s 指向新的内存空间(“word”的空间)了,hello没有变还在原来的地方。
参数传递方式:值传递和引用传递
public class Temp {
public static void m(StringBuffer s, int i) {
s.append("world");
i = 8;
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("Hello");
int i = 1;
m(s,i);
System.out.println("s="+s+"\n"+"i="+i);
}
}
运行结果:
s=Helloworld
i=1
可见引用类型的实例 s 中形参改变实参,而基本类型 i 实参没有被改变
“==” “equals” “hashCode”的区别?
== 比较的是引用的值(地址)
equals 比较的是引用指向的堆内存中的值(需要重写,默认为 ==,String已经被重写)
hashCode
如果俩个对象equals相同,那么hashCode也相同
如果俩个对象的hashCode不相同,那么equals不相同
为什么集合类没有实现Cloneable和Serializable接口?
克隆(cloning)或者序列化(serialization)的语义和含义是跟具体的实现相关的。因此应该由集合类的具体实现类来决定如何被克隆或者序列化
Iterator和ListIterator的区别
1.ListIterator只能用于List,Iterator用于List和Set
2.Iterator容易引起并发修改异常问题,而ListIterator可以避免线程安全问题的发生,因为其有内置的add()等修改集合的方法。
3. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
4. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
什么是类?继承?多态?抽象类?接口?内嵌类?
类:具有相同属性和行为的集合
继承:子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或 子类从父类继承方法,使得子类具有父类相同的行为。
多态:同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作
多态存在的三个必要条件:
继承、重写、父类引用指向子类对象
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处 理。
多态实现机制:覆盖、重载
抽象类:在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并 不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘 一个具体的对象,这样的类就是抽象类。(拥有抽象方法的类)
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方 法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为 这个原因,通常在设计阶段决定要不要设计抽象类。
1) 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编 译无法通过。只有抽象类的非抽象子类可以创建对象。
2) 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
3) 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实 现也 就是方法的具体功能。
4) 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
5) 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是 抽象类。
接口:在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以 interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法
1)接口中的方法会被隐式的指定为 public abstract(只能是 public abstract, 其他修饰符都会报错)。
2)接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量
3)接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的 方法
代码的执行顺序
父类静态变量
父类静态块
子类静态变量
子类静态块
父类非静态变量
父类非静态代码块
父类构造方法
子类非静态变量
子类非静态代码块
子类构造方法
抽象类和接口的区别
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行(java8之前)。
2) 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的,而且必须赋初值;抽象类里方法可以是各种的,接口里必须是public abstract。
3) 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
4) 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
使用super注意什么?
super()要放在方法里的最前面
数据类型转换规则
满足
byte->short->int->long->float->double
char -> int
也即 低精度-->高精度 不需要强制转换,反之需要
String、StringBuffer、StringBuilder区别
String不可变,效率低,赋值、构造方法方法进行实例化
StringBuffer可变,效率较高,安全,同步,适用于单/多线程,构造方法方法进行 实例化
StringBuilder可变,效率高于StringBuffer,不安全,异步,适用于单线程,构造方 法方法进行实例化
注:String类型修改时,创建一个StringBuilder,调用append()方法,最后调用 StringBuilder的toString()方法把结果返回
示例:
String s = “Hello”;
s += “World”;
以上代码等价下述代码:
StringBuilder sb = new StringBulider(s);
sb.append(“World”);
可见,如果经常改变字符串内容的话,会产生临时对象和附加操作
所以说,单线程下使用StringBuilder效率更高
StringBuffer 的扩容机制
空构造默认是16,字符串构造是字符串长度+16
扩容:新容量= 旧容量*2+2 , if 判断一下 容量如果不够,直接扩充到需要的容量大小。
数组
二维数组创建时列号可以不同,如下:
int arr[][] = new int {{1,2},{3,4,5}}
String常用方法
Date类应用
finally块中的代码什么时候执行?
在return语句之前执行而且一定会执行(进入到try块后)。如果try{}或者catch{}和finally{}中都有return,那么finally{}中的return会覆盖其他的return,最终会执行finally{}中的return
(1).finally块不会执行的情况:
1.未进入到try块就出现异常
2.在try块中强制退出时,如:System.exit(0);
(2).try中返回的变量,在finally块中对其操作时,对基本变量没影响,对引用变量有影 响
捕获异常的顺序
先捕获子类异常再捕获基类异常,否则子类异常将不会执行
异常分类
Throwable 最高层
|____Error 编译时错误
|____Exception 运行时异常
Throwable有两个子类,Error和Exception。其中Error是错误,对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。Exception,是另外一个非常重要的异常子类。它规定的异常是程序本身可以处理的异常。异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。
你是如何调用 wait()方法的?使用 if 块还是循环?为什么?
if可能出现假唤醒,应该用while(condition)。因为当wait这步被唤醒时,很可能condition已经不满足了,所以还需要判断condition。
10个线程和2个线程的同步代码,哪个更容易写?
从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互独立的。但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。
常用集合的分类:
Collection 接口的接口 对象的集合(单列集合)
├——-List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————--└ Vector 接口实现类 数组, 同步, 线程安全
│ ———————-└ Stack 是Vector类的实现类
└——-Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-HashSet 使用hash表(数组)存储元素,HashMap实现
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————-TreeSet 底层实现为二叉树,元素排好序
Map 接口 键值对的集合 (双列集合)
├———Hashtable 接口实现类, 同步, 线程安全(key和val不能为null)
├———HashMap 接口实现类 ,异步, 线程不安全(一个key为null,val可以多个为null)
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap
HashTable和HashMap的比较
List和set的区别
ArrayList、LinkedList、Vector的区别
Map的主要方法
JDBC技术应用
JDBC连接过程
Try{
//加载数据库驱动,注册到驱动管理器
Class.forName("com.mysql.jdbc.Driver ");
String oraURL= "jdbc:mysql://localhost:3306/db";
//获取Connection对象
Connection con=DriverManager.getConnection(oraURL, username,password);
Statement statement =con.createStatement();
String query = "SELECT name, pwd FROM sometable";
ResultSet resultSet= statement.executeQuery(query);
while(resultSet.next()){
name =resultSet.getString(1);
phone =resultSet.getString(2);
System.out.println(name+","+phone);
}catch(SQLException e){
se.printStackTrace();
} finally{ // 关闭资源
try{
if(resultSet != null)
resultSet.close();
if(stmt!=null)
stmt.close();
if(conn!=null)
conn.close();
}catch(SQLException e){
e.printStackTrace();
}