目录
Java语言基础部分
JVM?JDK?JRE?
Java语言的特点
Java语言的特性
基本数据类型
byte常用在什么地方
数据输入
常用Math方法(静态)
switch语句
跳转语句 break和continue
如何在main()方法之前输出”Hello World”?
java中的 clone()方法作用?
浅复制和深复制的区别?
Java反射机制
什么是String不可变
参数传递方式:值传递和引用传递
“==” “equals” “hashCode”的区别?
为什么集合类没有实现Cloneable和Serializable接口?
Iterator和ListIterator的区别
什么是类?继承?多态?抽象类?接口?内嵌类?
代码的执行顺序
抽象类和接口的区别
使用super注意什么?
数据类型转换规则
String、StringBuffer、StringBuilder区别
StringBuffer 的扩容机制
数组
String常用方法
Date类应用
finally块中的代码什么时候执行?
捕获异常的顺序
异常分类
多线程
你是如何调用 wait()方法的?使用 if 块还是循环?为什么?
10个线程和2个线程的同步代码,哪个更容易写?
IO流
Java集合
常用集合的分类:
HashTable和HashMap的比较
List和set的区别
ArrayList、LinkedList、Vector的区别
Map的主要方法
JDBC技术应用
JDBC连接过程
持续ing.....
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 等。
面向对象
跨平台解释执行,一次编译到处执行
健壮性和安全性:编译运行过程中提示错误
支持多线程
封装
继承
多态:方法重载、方法覆盖
抽象
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两个取值。
读取文件时(如图片,声音,可执行文件)需要用字节数组来保存文件的内容
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);
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( x ){
case 0:
case 1:
...
}
1.Break:跳出当前循环体
2跳出多重循环:
out:
for(...){
for(...){
break out;
}
}
3.continue: 终止此次循环,继续下一次,不跳出循环体
用 static 块输出
复制对象,修改新的对象原对象不变
对于基本类型来说一样,对于引用类型才有区别
浅复制只是复制了引用,不复制引用所指向的对象
深复制即复制引用,也复制指向的对象
得到一个对象的类,可以获取类的方法和属性的一种机制;运行时创建对象,运行时调用对象的方法
常用方法:
//getMethods方法获得所有public的方法,包括继承而来
Method[] ms = c.getMethods();
//getDeclaredMethods是获取该类自己的声明的方法
Method[] ms = c.getMethods();
//获取类中属性
Field[] fs = c.getDeclaredFields();
Constructor[] cs = c.getConstructors();
获取类:
创建对象的方式:
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 比较的是引用指向的堆内存中的值(需要重写,默认为 ==,String已经被重写)
hashCode
如果俩个对象equals相同,那么hashCode也相同
如果俩个对象的hashCode不相同,那么equals不相同
克隆(cloning)或者序列化(serialization)的语义和含义是跟具体的实现相关的。因此应该由集合类的具体实现类来决定如何被克隆或者序列化
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)接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的 方法
父类静态变量
父类静态块
子类静态变量
子类静态块
父类非静态变量
父类非静态代码块
父类构造方法
子类非静态变量
子类非静态代码块
子类构造方法
2) 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的,而且必须赋初值;抽象类里方法可以是各种的,接口里必须是public abstract。
3) 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
4) 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
super()要放在方法里的最前面
满足
byte->short->int->long->float->double
char -> int
也即 低精度-->高精度 不需要强制转换,反之需要
String不可变,效率低,赋值、构造方法方法进行实例化
StringBuffer可变,效率较高,安全,同步,适用于单/多线程,构造方法方法进行 实例化
StringBuilder可变,效率高于StringBuffer,不安全,异步,适用于单线程,构造方 法方法进行实例化
注:String类型修改时,创建一个StringBuilder,调用append()方法,最后调用 StringBuilder的toString()方法把结果返回
示例:
String s = “Hello”;
s += “World”;
以上代码等价下述代码:
StringBuilder sb = new StringBulider(s);
sb.append(“World”);
可见,如果经常改变字符串内容的话,会产生临时对象和附加操作
所以说,单线程下使用StringBuilder效率更高
空构造默认是16,字符串构造是字符串长度+16
扩容:新容量= 旧容量*2+2 , if 判断一下 容量如果不够,直接扩充到需要的容量大小。
二维数组创建时列号可以不同,如下:
int arr[][] = new int {{1,2},{3,4,5}}
在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,是另外一个非常重要的异常子类。它规定的异常是程序本身可以处理的异常。异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。
if可能出现假唤醒,应该用while(condition)。因为当wait这步被唤醒时,很可能condition已经不满足了,所以还需要判断condition。
从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互独立的。但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。
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
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();
}