Java 基础篇整理-1

最近在复习一下Java的一些基础东西,我整理了一部分,有错误的地方大家可以留言,部分内容我也是从网上学习(抄袭)来的,后续还会复习整理。
1.Java语言得特点:
1.简单易学,上手容易  2.可跨平台(在自己得JVM上运行)  3.安全性高  4.面向对象思想  5.支持多线程
 
2.java的八大基本数据类型: 
byte(1),short(2),int(4),long(8),float(4),double(8),boolean,char(2)
 
3.instanceof 的含义和用法:
用于检测对象是否是指定class 的子类,类实例,或接口实现类
 
4.java 的自动装箱和拆箱
装箱:将基本数据类型转换成包装类型(引用类型)  例:int -> Integer( Integer.valueof(int) )   Integer i = 10;(自动装箱,自动将int 包装成 Integer)
拆箱:将包装类型转换成对应的基本数据类型 :例:Integer i = 1; int in = i.intValue();
注意:(创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。)
注意:在某个范围内的整型数值的个数是有限的,而浮点数有无穷个。
 
5.重写与重载的区别:
重写:发生的子父类之间
        方法名称相同,参数相同,返回类型相同
        不能抛出比父类方法更多的异常
        重写方法 的访问修饰符必须高于 被重写的方法。
重载:发生在同一个类中
         方法名称相同,参数的个数,类型,顺序不同,返回类型可以不同
 
6.equals 和 == 的区别
== 是比较的栈中的对象地址是否相同,比较是否指向同一对象(堆),比较的实际意义是指针的比较。
equals是Object的一个方法,返回的是== 的结果。其他对象在不重写equals的情况下,equals 与 ==相同
 
7.String是一个只读字符串,并不是基本类型,StringBuffer和StringBuilder底层都是一个可操作的字符数组,StringBuffer是线程安全的,StringBuilder线程不安全
 
8.arrayList 和 linkedList的区别:
arrayList 底层是数组结构,linkedList底层是双向链表结构。
他们都是一个有序列表,保存的值可以相同
基于他们底层数据结构的问题,linkedList 删除和添加更快(如果是尾部添加 它们没啥差别),arrayList查询更快,arrayList可以指定下标查询。
linkedList对于内存的连续性要求低,arrayList相对高一些,因为arrayList底层是一个数组。
 
9.hashMap 和 hashTable 的区别
hashMap 的父类是AbstractMap,hashTable的父类是Dictionary
hashMap允许value为NULL,key只能有一个为NULL,hashaTable key 和 value 都不能为NULL
hashMap是线程不安全的,hashTable线程安全的
如果需要线程安全建议使用ConcurrentHashMap 程 因为他是分段所,知识锁定key hash后的那个桶。
hashTable 默认初始容量11  hashMap的初始值 16  (hashMap的初始值设定时会根据用户设定的参数计算一个正确的初始值,例如我们在初始化时设定 new HashMap(15)  hashmap经过计算,这时候我们的hashMap的最终初始值 是16)
hashTable 与  hashMap 的hash方法不相同
 
10.collection  和 collections 的区别
collection 是 集合的上级接口(list,set 都是继承了collection)
collections是集合的一个帮助类,主要提供一些排序,搜索,线程安全化(List<String> s = Collections.synchronizedList(new ArrayList<String>());
 
11.java的四种引用,强弱软虚
强引用:我们平常用的最多的,强引用在gc时不会被回收。( String s = new String("s") )
弱引用:弱引用就是只要gc发现了它,就会被回收。(WeakReference<String> wrf = new WeakReference<String>(str);)如果需要使用可以参考(java.util.WeakHashMap
另外两个不讲了都与弱引用差不太多。
 
12.Java创建对象的几种方式:
New创建新对象:
通过反射创建对象:(反射创建对象的方法是调用class 的 newInstance() 方法,其本质是调用Constructor<T>的newInstance()方法,
所以我们经常这么用:Constructor constructor = Employee.class.getConstructor();
             Employee emp3 = constructor.newInstance();
关于获取对象的Class 有一下几种方法 
//创建Class对象的方式一:(对象.getClass()),获取person类中的字节码文件
employee.class
//创建Class对象的方式二:(类.class:需要输入一个明确的类,任意一个类型都有一个静态的class属性)
Employee.class
//创建Class对象的方式三:(forName():传入时只需要以字符串的方式传入即可)
//通过Class类的一个forName(String className)静态方法返回一个Class对象,className必须是全路径名称;
//Class.forName()有异常:ClassNotFoundException
Class.forName("cn.itcast.Person");
通过Clone得方式创建对象:(需要注意:clone方法需要类实现Cloneable并重写clone方法,重写克隆方法后,类
得无参构造必选显式声明。拷贝也分深拷贝和浅拷贝,不了解得话可以百度。
通过序列化的方式创建对象:(ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
               Cat emp5 = (Cat) in.readObject();
               in.close();
               emp5.setName("Akash");
                 data.obj ObjectOutputStream 输出得一个对象序列化文件
 
13.不同的对象会不会存在相同的hashcode
存在的,因为hash冲突时不可避免的存在的。
当我们遇到这种情况时怎么处理那:
a:hashMap的处理方式:增加一个链表,在链表上放hashcode相同的对象
b:理论上来说可以在换一个hash算法
c:如果冲突了,随便找一个空地址先放着再说。
 
14.final 的相关特性和用法
 被final修饰的类不可以被继承
 被final修饰的方法不可以被重写
 被final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.
 被final修饰的方法,JVM会尝试将其内联,以提高运行效率
 被final修饰的常量,在编译阶段会存入常量池中
除此之外,编译器对fifinal域要遵守的两个重排序规则更好:
    在构造函数内对一个fifinal域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之
    间不能重排序
   初次读一个包含fifinal域的对象的引用,与随后初次读这个fifinal,这两个操作之间不能重排序.
   
15.关于static的用法
static 常用的静态方法,静态类,静态内部类,静态代码块,除了这些外还有一个不太常用的就是静态导包( import static .import 可以用来导入静态资源,在使用时可以不写类名
import static java.lang.Math.*;
    public class Test{
        public static void main(String[] args){
            //System.out.println(Math.sin(20));传统做法
            System.out.println(sin(20));
        }
}
 
16.关于浮点运算精度丢失问题:
 例如: 3*0.1  其结果就不等于0.3
           6*0.1  其结果也不能与0.6
 
17.a=a+ba+=b有什么区别吗?
+=会隐式的将右侧的数据强转成左侧的数据类型
           byte a = 127; byte b = 127;
           //b = a + b; // 报编译错误:cannot convert from int to byte
           b += a;
           System.err.println(b);
这里输出的是 -2 (我的计算方法:b = (127+1)->-128 +(127-1)->126  所以等于-2)
 
18.try catch finallytry里有returnfinally还执行么?
执行;早于try中return执行;
      public static String dd() {
           String name = "x";
           try {
                    return name = name+"j";
                } finally {
                    return name+"w";
                }
         }
看上边这个方法,它的返回值是多少,答案是xjw。  所以我们的结论是
 finally  和 try 里都有return时,先执行try中return 后的表达式但不反回结果,接着执行finally中的return并直接返回这个结果。
所以当我们写代码时finally中最好不要有return,否则结果可能不是你预期的。
 
19.Exception 和 error
在java中异常分为两种,运行时异常和非运行时异常(编码时编辑器就会报错,或者编译时直接报错)
运行时异常(RuntimeException)
ClassCastException(类转换异常)
NullPointerException(空指针异常)
IndexOutOfBoundsException(数组越界异常)
。。。。。 这些都是运行时异常。
非运行时异常是在我们编码需要显示的捕获或者抛出的异常。
error 程序错误(典型的内存溢出错误),它和运行时异常异常只有当发生时我们才知道。通常出现这种错误时程序会终止运行。
 
 
20. OOM你遇到过哪些情况,SOF你遇到过哪些情况
OOM
1OutOfMemoryError异常
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可
能。
Java Heap 溢出:
一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免
垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。
出现这种异常,一般手段是先通过内存映像分析工具(Eclipse Memory Analyzer)dump出来的堆转
存快照进行分析,重点是确认内存中的对象是否是必要的,先分清是因为内存泄漏(Memory Leak)还是
内存溢出(Memory Overflflow)
如果是内存泄漏,可进一步通过工具查看泄漏对象到GCRoots的引用链。于是就能找到泄漏对象是通过
怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收。
如果不存在泄漏,那就应该检查虚拟机的参数(-Xmx-Xms)的设置是否适当。
2,虚拟机栈和本地方法栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflflowError异常。
如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
这里需要注意当栈的大小越大可分配的线程数就越少。
3,运行时常量池溢出
异常信息:java.lang.OutOfMemoryError:PermGenspace
如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法。该方法的
作用是:如果池中已经包含一个等于此String的字符串,则返回代表池中这个字符串的String对象;否
则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。由于常量池分配在
方法区内,我们可以通过-XX:PermSize-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量
池的容量。
4,方法区溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。也有可能
是方法区中保存的class对象没有被及时回收掉或者class信息占用的内存超过了我们配置。
异常信息:java.lang.OutOfMemoryError:PermGenspace
方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,判定条件是很苛刻的。在
经常动态生成大量Class的应用中,要特别注意这点。
SOF(堆栈溢出StackOverflflow):
StackOverflflowError 的定义:当应用程序递归太深而发生堆栈溢出时,抛出该错误。
因为栈一般默认为1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量
超过1m而导致溢出。
栈溢出的原因:递归调用,大量循环或死循环,全局变量是否过多,数组、Listmap数据过大。
 
 
21.线程的基本情况:
下边是线程在运行过程的状态,共6种:
1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3.阻塞(BLOCKED):表示线程阻塞于锁。
4.等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5.超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
6. 终止(TERMINATED):表示该线程已经执行完毕。
 
 

线程的状态图

 
 
 
 
当线程执行 wait() 方法之后,线程进入 WAITING(等待)状态。进入等待状态的线程需要依靠其他
线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加
了超时限制,比如通过 sleeplong millis 方法或 waitlong millis 方法可以将 Java 线程置
 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步
方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable
 run() 方法之后将会进入到 TERMINATED(终止) 状态。
 
22.在java中如果对象不想被序列化应该怎么做
   transient 这个关键字了解一下, 在实现了Serializable的类中在不想被序列化的字段前用transient修饰 ,它只能修是变量,不能修饰方法和类。
 
23Java  IO 
Java  IO 流分为几种?
按照流的流向分,可以分为输入流和输出流;
按照操作单元划分,可以划分为字节流和字符流;
按照流的角色划分为节点流和处理流。
Java Io 流共涉及 40 多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的
联系, Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。
InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
按操作方式分类结构图:
 
 
 
详细了解可以参考: https://www.jianshu.com/p/715659e4775f
 
 
24、 Java IO NIO的区别
 
25、java反射的作用于原理
1、定义:
反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能
够调用它的任意一个方法。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。
这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
2、哪里会用到反射机制?
jdbc就是典型的反射
这就是反射。如hibernatestruts等框架使用反射实现的。
3、反射的实现方式:
第一步:获取Class对象,有4中方法:
1Class.forName(“类的路径”)
2)类名.class
3)对象名.getClass()
4)基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象
4、实现Java反射的类:
1Class:表示正在运行的Java应用程序中的类和接口
注意: 所有获取对象的信息都需要Class类来实现。
2Field:提供有关类和接口的属性信息,以及对它的动态访问权限。
3Constructor:提供关于类的单个构造方法的信息以及它的访问权限
4Method:提供类或接口中某个方法的信息
5、反射机制的优缺点:
优点:
1)能够运行时动态获取类的实例,提高灵活性;
2)与动态编译结合
缺点:
1)使用反射性能较低,需要解析字节码,将内存中的对象进行解析。
解决方案:
1、通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
2、多次创建一个类的实例时,有缓存会快很多
3ReflflectASM工具类,通过字节码生成的方式加快反射速度
2)相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)
 
26、说List,Set,Map三者的区别?
List(对付顺序的好帮手) List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的
对象
Set(注重独一无二的性质): 不允许重复的集合。不会有多个元素引用相同的对象(HashSet 底层存储用的是hashMap在存储数据)。
Map(Key来搜索的专家): 使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相
同的对象,但Key不能重复,典型的KeyString类型,但也可以是任何对象。
 
27。讲一下hashMap的底层实现
hashMap 是我们经常用到的集合,以Key-value形式保存数据,底层采用数组+链表(或者红黑树),HashMap的默认初始数组大小16(至于为什么是10 是因为需要减少hash碰撞,所以其数组大小始终是2的N次幂)
加载因子0.75
这是HashMap 的 链表与红黑树转换阈值:
/**
* 使用红黑树(而不是链表)来存放元素。当向至少具有这么多节点的链表再添加元素时,链表就将转换为红黑树。
* 该值必须大于2,并且应该至少为8,以便于删除红黑树时转回链表。
*/
static final int TREEIFY_THRESHOLD = 8;
 
/**
* 当桶数组容量小于该值时,优先进行扩容,而不是树化:
*/
static final int MIN_TREEIFY_CAPACITY = 64;
更具体一些,当put元素时,当链表满足上面阈值时会先put进第九个元素,在将链表转换成红黑树。