java知识点

1.equals和“==”号的区别:

  • 恒等号用于匹配内存单元的内容:对于原始类型比较的是值,对于引用类型比较的是地址。对于String类型的比较的是值而不是地址,主要原因是String源码帮我们重写了equals方法。
  • equals()方法再Object类中被定义,它的定义是使用的恒等的方式来匹配的。如果不重写equals()方法,那么它和恒等的功能是一样的。   
  • 对于引用类型(数组,对象,接口)当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。

    对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。 

2.StringBuilder.append()与String“+”的区别:

  • 首先,对于编译时就优化了的String“+”操作,不需要在运行时分配空间。它的效率自然而然的要比StringBuilder.append()高很多。
  • 未进行编译优化的情况:String“+” eg:String a="a",b="b";String c=a+b;(这句话在内存中的实际操作是这样的:StringBuilder temp=new StringBuilder();temp.append(a);temp.append(b);String c=temp.toString()) 如果把这句话放在循环语句中就会导致不断的new StringBuilder(),占用很多堆空间。而如果不用加操作而是在for循环的外面事先定义一个temp,那么就不会有多次的new StringBuilder()操作。但是现实应用中几乎没有人要一个字符串不断的叠加,而是反复叠加一些小的字符串来进行操作。

3.this和super的区别:

  • this:this只能用在方法体内,是调用方法的那个对象的引用。同一个类不同的对象,this不同。(在一个构造函数中调用本类中其他的构造函数(只能调用一条),this.name(被屏蔽的成员变量)=name(与成员变量同名的参数),this.fun()(this表示该函数所属类的当前对象的引用))
  • super:super关键字和this作用类似,用来引用直接父类(超类)中被屏蔽的成员变量和成员方法。(super.fun()表示当前类重写了父类的方法,然后用super调用被屏蔽的父类中成员方法)

4.ArrayList和linkedList的区别:

  • LinkedList:除了实现List接口外,还提供了insert,remove,get在尾部或者首部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。它是不同步的,在多线程的情况下可以如此同步:List list = Collections.synchronizedList(new LinkedList(...));
  • ArrayList:实现了可变大小的数组。除了实现List接口外,还提供size,isEmpty,get,set等方法。每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。它也是不同步的。
  • ArrayList是按照数组存储的,而LinkedList是按照链表存储的,LinkedList的迭代add()操作要比ArrayList要快很多,但是如果你事先指定了ArrayList的大小例如:ArrayList<String> s=new ArrayList<String>(1000);那么我们操作的时候就是对一个固定的数组进行操作,这个对LinkedList来说是不公平的,因为linkedlist每次都要先增加节点,然后再添加数据。

5.ArrayList和Vector的区别:

  • 同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。
  • 数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半

6.Vector和Stack的区别:

  • Vector:Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。
  • Stack:Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

7.Collection和Map的区别:

  •  Collection:只允许每个位置上放一个对象。它包括“以一定顺序持有一组对象”的List,以及“只能允许添加不重复对象”的Set。你可以用add()方法向Collection对象中加元素。
  •  Map:一组以“键-值”(key-value)的形式出现的pair,Map也不接受重复的key值。你可以用put()方法往Map里面加元素。
  •  可以根据其每个位置存放对象的方式来区别Collection和Map。

8.Collection 和 Collections的区别:

  • Collections是个java.util下的类,它包含有各种有关集合操作的静态方法,实现对各种集合的搜索、排序、线程安全化等操作。
  • Collection是个java.util下的接口,它是各种集合结构的父接口。继承自它的接口主要有Set 和List.

9.同步和不同步的区别:

  • 同步:多线程的时候是线程安全的。
  • 不同步:多线程的时候需要自己加同步锁来保证线程安全。

10.HashMap和HashTable的区别:

  • HashTable的应用非常广泛,HashMap是Hashtable的轻量级实现(非线程安全的实现),HashMap是新框架中用来代替HashTable的类,也就是说建议使用HashMap,不要使用HashTable。
  • HashTable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。
  • HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。
  • HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
  • HashTable使用Enumeration,HashMap使用Iterator。

11.重载和重写的区别:

  • 重载:对于类的方法(包括从父类继承的方法),方法名相同,方法的参数列表不同,就这样称为函数的重载。函数的重载是多态性的表现。
  • 重写:也称为覆盖,当父类的方法没有办法满足子类的需要时,子类会改写父类的方法,当父类的方法被覆盖的时候,除非通过super来调用父类的方法,否则无法调用。
  • 重写的条件是:返回值,方法名,参数列表必须完全相同。而且子类的方法的访问权限不能低于父类。简称:三同一不低。
  • 不能重写的原因:该方法被final修饰无法覆盖,被private修饰无法覆盖只是新定义方法而已,被static修饰无法覆盖静态方法是在编译的时候就和类的引用类型匹配。

12.集合数据类型中数组,List,Set,Map之间的区别:

  • 数组:有顺序,同样类型的数据,有长度,允许有相同元素。
  • List:有顺序,不同类型的数据,没有长度,允许有相同元素。
  • Set:无顺序,不同类型的数据,没有长度,不允许有重复元素。
  • Map:键值对数据,HashMap,HashTable等(Key值不同)。

13.String,StringBuffer,StringBuilder区别:

  • String:是一个final类,因此如果对String类型的字符串进行修改,实际上是指向了一个新的字符串,而不是原来的串。因此经常要改变的字符串一定不要用String类型。 ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
  • Java.lang.StringBuffer线程安全的可变字符序列。可将字符串缓冲区安全地用于多个线程,StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
  • java.lang.StringBuilder一个线程不安全可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
  • StringBuffer和StringBuilder在很多情况下是可以等价的。每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

14.final,finally,finalize区别:

  • 1.final修辞
  • final修辞变量分为两种:基本类型(byte,short,int,long,float,double,char,boolean)也是值类型,则一旦初始化,值不能改变;应用类型(String,Date等),则是引用不能变。
  • final修辞函数,则函数不能重写。
  • final修辞类,则类不能被继承,但是类中的元素可以被修改。
  • 2.finally:try后面的语句块之一,无论异常是否抛出,都会执行的语句块
  • 3. finalize()方法是在 GC 清理它所从属的对象时被调用的,如果执行它的过程中抛出了无法捕获的异常 (uncaught exception),GC 将终止对改对象的清理,并且该异常会被忽略;直到下一次 GC 开始清理这个对 象时,它的 finalize()会被再次调用。 由于 finalize()属于 Object 类,因此所有类都有这个方法,Object 的任意子类都可以重写(override)该方法, 在其中释放系统资源或者做其它的清理工作,如关闭输入输出流。

15.eqauls方法和hashCode方法关系在两个都没有重写的情况下:

hashCode()方法返回的就是一个数值,从方法的名称上就可以看出,其目的是生成一个hash码。hash码的主要用途就是在对对象进行散列的时候作为key输入,事实上,Object类提供的默认实现确实保证每个对象的hash码不同(在对象的内存地址基础上经过特定算法返回一个hash码)。

Java对于eqauls方法和hashCode方法()是这样规定的: 

(1)同一对象上多次调用hashCode()方法,总是返回相同的整型值。

(2)如果a.equals(b),则一定有a.hashCode() 一定等于 b.hashCode()。 

(3)如果!a.equals(b),则a.hashCode() 不一定等于 b.hashCode()。此时如果a.hashCode() 总是不等于 b.hashCode(),会提高hashtables的性能。

(4)a.hashCode()==b.hashCode() 则 a.equals(b)可真可假

(5)a.hashCode()!= b.hashCode() 则 a.equals(b)为假。

16.为什么覆盖equals时总要覆盖hashCode   

一个很常见的错误根源在于没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable。

1.在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。

2.如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。

3.如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生相同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。

17.堆和栈的区别:

堆与栈 Java的堆是一个运行时数据区,类的对象从中分配空间。这些对象通过new、newarray、 anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。

堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存 大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态 分配内存,存取速度较慢。

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是 确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。

18.java中的异常和错误

    在java.lang软件包中有一个java.lang.Throwable类,这个类是java中所有错误和异常的超类。

    在java中错误和异常的继承主要有两个: 分别为Error和Exception 这两个。

    Error:是java中所有错误类的父类,就是jvm出现错误,以及系统蹦溃等现象,这些错误没办法通过程序来处理,对于系统错误,一般不需要开发人员处理(也无法处理), 比如内存溢出(Out of Memory)和线程死锁等系统问题。所以在程序中需要使用catch来捕捉处理这类的错误或者使用throw来抛出相关的异常。

    Exception:  又可以分为checkedException(编译时异常) 和RuntimeException(运行时异常) 这两种异常。

  • checkedException异常在进行编译的时候就可以知道会不会发生异常,如果不对这些异常进行抛出、捕获的话就不能通过编译,如在使用java的io读取文件的时候,可能会会出现所读取的文件不存在的情况 对于,对于这类编译时的异常必须手动去处理它们(捕获或者抛出)。否则的话是无法正常通过编译器的。 
  • RuntimeException就是运行的时候出现的异常,在之前你是没办法确定是不是会出现异常。这类异常仅仅在程序运行的过程中才会发现。比如数组下标越界(ArrayIndexOutOfBoundsException),强制转换报错(ClassCastException,一部分),空指针异常(NullPointerException)除数为零(/ by zero) 对于这类运行时的异常是否抛出, 由用户根据自身的情况 决定是否抛出异常。java并不强制要求用户 一定处理。
原文地址:https://www.cnblogs.com/hupp/p/4669890.html