zoukankan      html  css  js  c++  java
  • Java理论-Java高级

    反射的用途及实现

    Java反射机制主要提供了以下功能:在运行时构造一个类的对象;判断一个类所具有的成员变量和方法;调用一个对象的方法;生成动态代理。
    反射最大的应用就是框架。
    Java反射的主要功能:

    1. 确定一个对象的类。
    2. 取出类的方法,构造器,属性和超类。
    3. 找出某个接口里定义的常量和方法说明。
    4. 创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象)。
    5. 取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做到。
    6. 在运行时刻调用动态对象的方法。
    7. 创建数组,数组大小和类型在运行时刻才确定,也能更改数组成员的值。

    List 、 Set 、 Map 区别

    List,Set都是继承自Collection接口。
    List特点:元素有放入顺序,元素可重复。
    Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉。
    List和Set、Map对比:
    List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
    Set:查找元素效率低,删除和插入效率高,插入和删除不会引起元素位置改变。
    Map是键值对的集合,不允许key重复。

    什么场景下使用list,set,map

    1. 如果你经常会使用索引来对容器中的元素进行访问,那么List是你的正确的选择。如果你已经知道索引了的话,那么List的实现类比如ArrayList可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。
    2. 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是List,因为List是一个有序容器,它按照插入顺序进行存储。
    3. 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个Set的实现类,比如HashSet、LinkedHashSet或者TreeSet。所有Set的实现类都遵循了统一约束比如唯一性。LinkedHashSet也按照元素的插入顺序对它们进行存储。
    4. 如果你以键和值的形式进行数据存储那么Map是你正确的选择。你可以根据你的后续需要从HashTable、HashMap、TreeMap中进行选择。

    ArrayList 与 LinkedList 区别

    Arraylist:
    优点:Arraylist是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
    缺点:因为地址连续,Arraylist要移动数据,所以插入和删除操作效率比较低。
    LinkedList:
    优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作,LinkedList比较占优势。
    LinkedList适用于头尾操作或插入指定位置的场景。
    缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
    适用场景分析:当需要对数据进行多次访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

    HashMap 和 Hashtable 的区别

    1. HashMap去掉了Hashtable的contains方法,但是加上了containsValue()和containsKey()方法。
    2. Hashtable同步的,而HashMap是非同步的,HashMap效率上比Hashtable要高。
    3. HashMap允许空键值,而Hashtable不允许。

    HashSet 和 HashMap 的区别

    1. Set是线性结构,Set中的值不能重复,HashSet是Set接口的实现类,HashSet中值不能重复是用HashMap的key来实现的。
    2. Map是键值对映射,允许空键值。HashMap是Map接口的实现类,key的唯一性是通过key值hash值的唯一来确定,value值是则是链表结构。
    3. 他们的共同点都是hash算法实现的唯一性,都不能持有基本类型,只能持有对象。

    创建线程的方式及实现

    Java中创建线程主要有三种方式:

    1. 继承Thread类创建线程类。
    2. 通过Runnable接口创建线程类。
    3. 通过Callable和Future创建线程。

    线程池的几种方式

    1. newFixedThreadPool(int nThreads):创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。
    2. newCachedThreadPool():创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。
    3. newSingleThreadExecutor():这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。
    4. newScheduledThreadPool(int corePoolSize):创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

    线程的生命周期

    生命周期的五种状态:

    1. 新建(new Thread)
      当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
      例如:Thread t1 = new Thread();
    2. 就绪(runnable)
      线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
    3. 运行(running)
      线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
    4. 死亡(dead)
      当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
      自然终止:正常运行run()方法后终止
      异常终止:调用stop()方法让一个线程终止运行
    5. 堵塞(blocked)
      由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
      正在睡眠:用sleep(long t)方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
      正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
      被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

    Java GC机制

    为了分代垃圾回收,Java堆内存分为3代:新生代,老年代和永久代。
    GC是针对可达性分析法进行回收,当新生代满了开始GC,会进行Minor GC,升到老年代的对象大于老年代剩余空间时会进行Major GC。新生代采用复制算法,老年代采用清除或标记-整理算法。
    Java中不能手动触发GC,但可以用不同的引用类来辅助垃圾回收器工作(比如:弱引用或软引用)。

    如何线程安全的使用HashMap

    HashMap不是线程安全的;Hashtable线程安全,但效率低,因为是Hashtable是使用synchronized的,所有线程竞争同一把锁;而ConcurrentHashMap不仅线程安全而且效率高,因为它包含一个segment数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术。

    如何线程安全的使用HashMap,无非就是使用以下三种方式。

    • Hashtable:源码中是使用synchronized来保证线程安全的,比如get方法和put方法,所以当一个线程访问Hashtable的同步方法时,当其他线程也要访问同步方法,会被阻塞住。
    • ConcurrentHashMap:允许并发的读和线程安全的更新操作,所有操作都是线程安全,不允许null的键值,可以用来代替Hashtable,但要不会锁住整个Map。
    • Synchronized Map:当调用synchronizedMap()方法后会返回一个SynchronizedMap类的对象,而在这个类中使用了synchronized同步关键字来保证对Map的操作是线程安全的。
    // Hashtable
    Map<String, String> hashtable = new Hashtable<>();
    // synchronizedMap
    Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>());
    // ConcurrentHashMap
    Map<String, String> concurrentHashMap = new ConcurrentHashMap<>();
    
    

    HashMap是如何解决冲突的

    其实就是链接法,将索引值相同的元素存放到一个单链表里。但为了解决在频繁冲突时HashMap性能降低的问题,Java 8中做了一个小优化,在冲突的元素个数超过设定的值(默认为8)时,会使用平衡树来替代链表存储冲突的元素。
    通常情况HashMap,HashTable,HashSet,LinkedHashSet,LinkedHashMap,均采用这种方法处理冲突。
    从JDK 8开始,HashMap,LinkedHashMap和ConcurrentHashMap为了提升性能,在频繁冲突的时候使用平衡树来替代链表。

    Java创建对象有哪几种方式

    大概有四种:new,工厂模式,反射和克隆。

    • 工厂模式:是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
      在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
    • 反射:能够让运行于JVM中的程序检测和修改运行时的行为。将Class类中的forName和newInstance配合使用,可以根据存储在字符串中的类名创建一个对象。
      通过反射,我们能够在运行时检测对象的类型;动态构造某个类的对象;检测类的属性和方法;任意调用对象的方法;修改构造函数、方法、属性的可见性。
    • 浅复制(浅克隆):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
    • 深复制(深克隆):被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

    注解

    在自定义注解时需要使用的两个主要的元注解@Retention和@Target。
    @Retention用来声明注解的保留策略,有CLASS,RUNTIME,SOURCE三种,分别表示注解保存在类文件,JVM运行时刻和源代码中。
    @Target用来声明注解可以被添加到哪些类型的元素上,如类型,方法和域等。

    解释一下java.io.Serializable接口?

    类通过实现 Java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。

    PrintStream、BufferedWriter、PrintWriter的比较

    • PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。
      与其他输出流不同,PrintStream永远不会抛出IOException;而是,异常情况仅设置可通过checkError方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream。
    • BufferedWriter:将文本写入字符输出流,缓冲各个字符从而提供单个字符,数组和字符串的高效写入。通过write()方法可以将获取到的字符输出,然后通过newLine()进行换行操作。BufferedWriter中的字符流必须通过调用flush方法才能将其刷出去。并且BufferedWriter只能对字符流进行操作。如果要对字节流操作,则使用BufferedInputStream。
    • PrintWriter的println方法自动添加换行,不会抛异常,若关心异常,需要调用checkError方法看是否有异常发生,PrintWriter构造方法可指定参数,实现自动刷新缓存(autoflush)。

    什么是Java序列化,如何实现Java序列化?

    Java对象的序列化指将一个Java对象写入IO流中,与此对应的是,对象的反序列化则从IO流中恢复该Java对象。
    如果要让某个对象支持序列化机制,则必须让它的类是可序列化的,为了让某个类是可序列化的,该类必须实现Serializable接口或Externalizable接口

    强引用、软引用、弱引用、虚引用以及他们与GC的关系

    强引用:new出的对象之类的引用,
    只要强引用还在,永远不会回收
    软引用:引用但非必须的对象,内存溢出异常之前,回收
    弱引用:非必须的对象,对象能生存到下一次垃圾收集发生之前。
    虚引用:对生存时间无影响,在垃圾回收时得到通知。

  • 相关阅读:
    vim的强大,vim设置和插件的使用,脱离windows才是王道
    [VS2013]如何闪开安装VS2013必须要有安装IE10的限制
    常用客户端实现逻辑
    开源控件ViewPagerIndicator学习
    常用设计模式
    主题演讲:未来新趋势电动车
    你最美好的年华
    一度总结
    android线程池ThreadPoolExecutor的理解
    Touch事件or手机卫士面试题整理回答(二)
  • 原文地址:https://www.cnblogs.com/mihuk/p/13296147.html
Copyright © 2011-2022 走看看