java进阶复习——常见易错点总结
本博文用于记载java进阶中一些难点和易混淆的知识点,并不详细,也不全面,适合有java基础的朋友进行复习巩固。
(部分内容为从PPT中拷贝,侵删)
里面编号有点问题,以后再改吧,先凑合着看看
一、反射
反射中我们可以通过Class
对象来反射出一个类的构造方法、方法、属性、注释以及内部类。
在通过反射获取构造方法的适合,有四种不同的方法。
Constructor<T> getConstructor(Class<?>..ParameterType)
: 返回此Class对象所表示的类的指定的public构造器
Constructor<?>[] getConstructors()
: 返回此Class对象所表示的类的所有public构造器
Constructor<T> getDeclaredConstructor(Class<?>..ParameterType)
: 返回此Class对象所表示的类的指定的public构造器,与构造器的级别没有关系。
Constructor<?>[] getDeclaredConstructors()
: 返回此Class对象所表示的类的所有构造器
而getConstructor
和getDeclaredConstructed
之间的区别,很简单,就在于getConstructor
只能获取用public
申明的符合条件(参数列表匹配)的构造函数,而getDeclaredConstructed
可获取所有的符合条件的的构造函数,不局限于public
,也可以使private
等。
用Class对象创建一个新对象的方式为class.newInstance()
,或者class.getConstructor(Class<?>..ParamterType).newInstance()
区别在于前者使用的是默认无参构造函数,而后者使用的是自己需要的构造函数,而需要选择哪一个构造函数则是在getContructor()
里面的参数设置了
获取类方法采用getMethod()
,获取类字段使用getField()
.
如果是八大基本类型,可以使用getxxx()
,这个xxx就是基本类型,当然同样的有对应的set方法。
二、泛型
java泛型其实不难,讲几个易错点吧。
- 子类继承自带泛型的父类时,可以不加泛型,但是如果加了泛型就不要写成
<T>
,而应写成一个具体的类型,比如<String>
- 系统没有真正的泛型类,因此在类型判断中使用
if( c instanceof ArrayList<String>)
是错误的 - 定义泛型方法:
修饰符 <T,S> 返回值类型 方法名(形参列表){
…….//方法体
}
- 泛型类型不具有父子关系:比如
ArrayList<String>
和ArrayList<Object>
之间不具有父子关系 - 泛型中,如果通配符写成了
?
,那么不允许向该泛型集合中添加任何元素,除了null。比如:List<?> list = new ArrayList();
那么list.add(1);
是错误的。 ?
的意义在于它可以控制传入的参数类型:比如在方法参数申明中void foo(List<? extends Circle> list)
- 同样可以用
?
设置下界,比如:(x super Student)
,那么x必须是Student
类或者其父类 - 泛型参数不适用于为静态变量设置类型
三、多线程
- 并发与并行:经典问题,并发是同一时间段内多个程序执行,而并行是同一时刻。
- 多线程两种方式,继承自
Thread
,或者实现Runnable
接口 - 重写的是
run()
方法,调用的是start()
方法,如调用run()
方法不能实现多线程,原因不详述了。 - 不要对已死亡的线程调用
start()
方法,也不要对同一个thread
调用两次start()
,会抛异常的 - 实现Runnable接口的类可以作为多个线程的实例被调用,讲人话就是其中公共字段会被公用。
yield
方法,就是退出运行状态转为就绪状态,而下一个进入运行状态的线程,可能仍然是该线程,也可能不是,这时要看CPU如何选择了。清楚解析请看:https://blog.csdn.net/dabing69221/article/details/17426953Thread.setDaemon(true)
可将当前线程设置为后台线程,而用isDaemon()
可以判断是否为后台线程- 线程同步常采用的方式有两种,设置
synchronized
或者 手动加锁 synchronized
同步代码块,必须要对某个对象加锁,不然怎么能叫同步呢。加锁方式有两种,当对某一个方法加锁时,不需要手动设置加锁的对象,因为加锁的只能(同时也默认)是this
,写法为:
public synchronized void method(){
xxx
}
而如果是对某一个代码块设置synchronized
同步锁,则必须设置锁的对象,比如:
public void method_1(){
sychronized(this){
// 这个是锁当前对象;
}
public void method_2(People p){
synchronized(p){
// 这里是对p这个对象加锁;
}
}
}
推荐参考博客:https://blog.csdn.net/luoweifu/article/details/46613015
- lock的用法:
volatile
关键字,可以在申明一个变量的时候加在前面进行修饰,其作用为让这个变量的值一旦在某一个线程中被修改,会立刻存到内存。说起来很玄乎,其实反映到硬件层面,就是让其缓存行失效。但是它只能保证可见性,不保证原子性。想详细了解的看博客,从第四大点看起就好了:https://www.cnblogs.com/dolphin0520/p/3920373.htmlThreadLocal
解决线程同步问题:ThreadLocal
修饰的变量会在每一个线程中创建一个副本,且只能被当前线程访问,因此就保证了数据的线程安全性。- 线程通知机制有两组,分别是
wait()、notify()、notifyAll()
和await(),signal(),sianalAll()
。而wait()
和await()
这两个家伙貌似没什么区别,即便是在英文含义上也没什么区别,不过是wait是不及物动词,而await是及物动词,哈哈哈跑题了。相对而言,wait()
常用于synchronized
块中,而await()
常见于lock
中,他们一定要在锁里面出现!!! - 我们知道wait()和await()的signal()等方法都是随机通知的,这就容易产生乱子了,而如果要实现选择性通知,那么就需要采用Condition来实现了。其定义方法如下:
Condition condition = reentrantLock.newCondition();
//在代码中则使用如下方式对指定的线程进行唤醒
condition.wait();
condition.signal();
Callable
和future
, 相当于有参数的Runnable
从这个网站拷下来的一些代码,看代码就很清楚了,不细说了:https://blog.csdn.net/ghsau/article/details/7451464
public class CallableAndFuture {
public static void main(String[] args) {
Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
};
FutureTask<Integer> future = new FutureTask<Integer>(callable);
new Thread(future).start();
try {
Thread.sleep(5000);// 可能做一些事情
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
- 线程池。不细讲了。
- 集合类是线程不安全的,线程安全的集合类有
ConcurrentHashMap
、ConcurrentLinkedQueue
,分别代表了支持并发的访问的HashMap
和支持并发访问的Queue
四、JDBC
JDBC是java连接数据库的方式,其需要对应数据库提供商提供需要的驱动。
JDBC编程步骤
1. 加载并注册数据库驱动Driver
2. 建立连接Connection
3. 创建执行对象Statement
4. 执行语句
5. 处理执行结果(ResultSet)
6. 释放资源
下面放上一个(有很多种方法)例子吧:
Class.forName(“com.mysql.jdbc.Driver”);
Connection conn =DriverManager.getConnection(url, user, password);
Statement st = conn.createStatement();
ResultSet rs =st.executeQuery(sql);
int flag = st.executeUpdate(sql);
rs.close();
st.close();
conn.close();
详细的请看这篇博客(以上也是这里总结出来的):https://blog.csdn.net/ljheee/article/details/50988796