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对象所表示的类的所有构造器

getConstructorgetDeclaredConstructed之间的区别,很简单,就在于getConstructor只能获取用public 申明的符合条件(参数列表匹配)的构造函数,而getDeclaredConstructed 可获取所有的符合条件的的构造函数,不局限于public,也可以使private等。

用Class对象创建一个新对象的方式为class.newInstance(),或者class.getConstructor(Class<?>..ParamterType).newInstance()
区别在于前者使用的是默认无参构造函数,而后者使用的是自己需要的构造函数,而需要选择哪一个构造函数则是在getContructor()里面的参数设置了

获取类方法采用getMethod(),获取类字段使用getField().
如果是八大基本类型,可以使用getxxx(),这个xxx就是基本类型,当然同样的有对应的set方法。


二、泛型

java泛型其实不难,讲几个易错点吧。

  1. 子类继承自带泛型的父类时,可以不加泛型,但是如果加了泛型就不要写成<T> ,而应写成一个具体的类型,比如<String>
  2. 系统没有真正的泛型类,因此在类型判断中使用if( c instanceof ArrayList<String>) 是错误的
  3. 定义泛型方法:
 修饰符  <T,S>  返回值类型   方法名(形参列表){
   …….//方法体
}
  1. 泛型类型不具有父子关系:比如ArrayList<String>ArrayList<Object>之间不具有父子关系
  2. 泛型中,如果通配符写成了,那么不允许向该泛型集合中添加任何元素,除了null。比如:List<?> list = new ArrayList();那么list.add(1);是错误的。
  3. 的意义在于它可以控制传入的参数类型:比如在方法参数申明中void foo(List<? extends Circle> list)
  4. 同样可以用设置下界,比如:(x super Student) ,那么x必须是Student类或者其父类
  5. 泛型参数不适用于为静态变量设置类型

三、多线程

  1. 并发与并行:经典问题,并发是同一时间段内多个程序执行,而并行是同一时刻。
  2. 多线程两种方式,继承自Thread,或者实现Runnable接口
  3. 重写的是run()方法,调用的是start()方法,如调用run()方法不能实现多线程,原因不详述了。
  4. 不要对已死亡的线程调用start()方法,也不要对同一个thread调用两次start(),会抛异常的
  5. 实现Runnable接口的类可以作为多个线程的实例被调用,讲人话就是其中公共字段会被公用。
  6. yield方法,就是退出运行状态转为就绪状态,而下一个进入运行状态的线程,可能仍然是该线程,也可能不是,这时要看CPU如何选择了。清楚解析请看:https://blog.csdn.net/dabing69221/article/details/17426953
  7. Thread.setDaemon(true)可将当前线程设置为后台线程,而用isDaemon()可以判断是否为后台线程
  8. 线程同步常采用的方式有两种,设置 synchronized 或者 手动加锁
  9. 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

  1. lock的用法:
    这里写图片描述
  2. volatile 关键字,可以在申明一个变量的时候加在前面进行修饰,其作用为让这个变量的值一旦在某一个线程中被修改,会立刻存到内存。说起来很玄乎,其实反映到硬件层面,就是让其缓存行失效。但是它只能保证可见性,不保证原子性。想详细了解的看博客,从第四大点看起就好了:https://www.cnblogs.com/dolphin0520/p/3920373.html
  3. ThreadLocal 解决线程同步问题:ThreadLocal修饰的变量会在每一个线程中创建一个副本,且只能被当前线程访问,因此就保证了数据的线程安全性。
  4. 线程通知机制有两组,分别是wait()、notify()、notifyAll()await(),signal(),sianalAll()。而wait()await() 这两个家伙貌似没什么区别,即便是在英文含义上也没什么区别,不过是wait是不及物动词,而await是及物动词,哈哈哈跑题了。相对而言,wait()常用于synchronized块中,而await()常见于lock中,他们一定要在锁里面出现!!!
  5. 我们知道wait()和await()的signal()等方法都是随机通知的,这就容易产生乱子了,而如果要实现选择性通知,那么就需要采用Condition来实现了。其定义方法如下:
Condition condition = reentrantLock.newCondition();

//在代码中则使用如下方式对指定的线程进行唤醒
condition.wait();
condition.signal();
  1. Callablefuture , 相当于有参数的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();
        }
    }
}
  1. 线程池。不细讲了。
  2. 集合类是线程不安全的,线程安全的集合类有ConcurrentHashMapConcurrentLinkedQueue,分别代表了支持并发的访问的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

posted @ 2018-05-14 19:42  _吟游诗人  阅读(153)  评论(0编辑  收藏  举报