zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Flink实战(七十三):FLINK-SQL使用基础(一)简介(一)入门
    Flink实战(七十二):监控(四)自定义metrics相关指标(二)
    k8s启动
    k8s containerd
    安装containerd
    k8s镜像
    crictl
    Kubernetes: Using containerd 1.1 without Docker
    docker images --digests
    ctr images pull docker.io/library/redis:latest
  • 原文地址:https://www.cnblogs.com/yinyoupoet/p/13287510.html
Copyright © 2011-2022 走看看