天天看点

javaSe个人难点总结

1.java关键字transient:

transient使用总结

(1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法被访问。

(2) transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

(3)一个静态变量不管是否被transient修饰,均不能被序列化(如果反序列化后类中static变量还有值,则值为当前JVM中对应static变量的值)。序列化保存的是对象状态,静态变量保存的是类状态,因此序列化并不保存静态变量。

使用场景

(1)类中的字段值可以根据其它字段推导出来,如一个长方形类有三个属性长度、宽度、面积,面积不需要序列化。

(2)一些安全性的信息,一般情况下是不能离开JVM的。

(3)如果类中使用了Logger实例,那么Logger实例也是不需要序列化的

2.java关键字native:

native关键字用法

native是与C++联合开发的时候用的!java自己开发不用的

使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。 这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。

1。native 是用做java 和其他语言(如c++)进行协作时用的 也就是native 后的函数的实现不是用java写的 2。既然都不是java,那就别管它的源代码了,呵呵

native的意思就是通知操作系统, 这个函数你必须给我实现,因为我要使用。 所以native关键字的函数都是操作系统实现的, java只能调用。

java是跨平台的语言,既然是跨了平台,所付出的代价就是牺牲一些对底层的控制,而java要实现对底层的控制,就需要一些其他语言的帮助,这个就是native的作用了

3.java关键字assert:

Java2在1.4中新增了一个关键字:assert。在程序开发过程中使用它创建一个断言(assertion)。,它的语法形式有如下所示的两种形式:

1、assert condition;

这里condition是一个必须为真(true)的表达式。如果表达式的结果为true,那么断言为真,并且无任何行动

如果表达式为false,则断言失败,则会抛出一个AssertionError对象。这个AssertionError继承于Error对象,

而Error继承于Throwable,Error是和Exception并列的一个错误对象,通常用于表达系统级运行错误。

2、asser condition:expr;

这里condition是和上面一样的,这个冒号后跟的是一个表达式,通常用于断言失败后的提示信息,说白了,它是一个传到AssertionError构造函数的值,如果断言失败,该值被转化为它对应的字符串,并显示出来。

用一个例子说明一下:

java public class Test { public static void main(String[] args) { System.out.println("start"); assert true; System.out.println("go on"); assert false:"stop"; System.out.println("end"); } }

这里有一个测试类,通过之前简单的语法介绍后,可以这样简单的理解这个例子:

当程序运行到assert true这一句时,condition为true,系统会继续执行下去。而后执行到 assert false:"stop"的时候,由于condition=false,系统会抛出AssertionError。

但是试试上是不是这样的呢?

看看运行结果就知道了

> start go on end

这个运行结果和我们一开始的预期不一致,问题出在哪里了?

原来java的断言与C语言中的断言还有有些不同的地方。

Java的assertion的开启也和C语言不太一样,在C语言中,assertion的开启是在编译时候决定的。当我们使用debug方式编译程序时候,assertion被开启,而使用release方式编译时候,assertion自动被关闭。 而Java的assertion却是在运行的时候进行决定的。其实,这两种方式是各有优缺点。如果采用编译时决定方式,开发人员将处理两种类型的目标码,debug版本和release版本,这加大了文档管理的难度,但是提高了代码的运行效率。 Java采用运行时决定的方式,这样所有的assertion信息将置于目标代码 中,同一目标代码可以选择不同方式运行,增强目标代码的灵活性,但是它将牺牲因为assertion而引起一部分性能损失。

说直白一点就是:assert关键字需要在运行时候显式开启才能生效,否则你的断言就没有任何意义。

4.Java关键字volatile的两层语义

  一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

  1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

  2)禁止进行指令重排序。

  

5.Java关键字instanceof:

严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:

boolean result = obj instanceof Class

  其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。

 注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行定。

  

6.Java关键字const:

const是java中的预留关键字(java中预留关键字还有goto),现在没有作为关键字,以后的版本中可能扩展用,但现在常用于C,C++中。C中的const类似于final。

7.Java枚举enum关键字

枚举的理解

枚举其实就是一个类,枚举类的实例是一组限定的对象

传统的方式创建枚举 【了解】

对比:单例类
1、构造器私有化
2、本类内部创建对象
3、通过public static方法,对外暴露该对象

枚举类
1、构造器私有化
2、本类内部创建一组对象,添加public static修饰符,直接暴露对象
           

八大排序算法

1、直接插入排序

2、希尔排序

3、简单选择排序

4、推排序

5、冒泡排序

6、快速排序

7、归并排序

8、桶排序

面向过程

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展

面向对象

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护

缺点:性能比面向过程低

Collection ——> List ——> ArrayList类

Collection ——> List ——> LinkedList类

Collection ——> Set ——> HashSet类

Collection ——> Set ——> SortedSet接口 ——> TreeSet类

Map ——> HashMap类

Map ——> SortedMap ——> TreeMap类

1、

List是一个有序集合,既存入集合的顺序和取出的顺序一致 List集合允许添加的元素重复

2、

  1. ArrayList和Vector都是基于数组实现的,两者用法差不多
  2. ArrayList随机查询效率高,随机增删元素效率较低
  3. Vector提供了一个Stack子类,模拟“栈”数据结构——”先进后出”
  4. ArrayList是线程不安全的,Vector是线程安全的

3、

LinkedList是双向链表实现的 随机查询效率低,随机增删效率高

4、

List主要有两个实现ArrayList和LinkedList,他们都是有顺序的,也就是放进去是什么顺序,取出来还是什么顺序

ArrayList——遍历、查询数据比较快,添加和删除数据比较慢(基于可变数组)

LinkedList——查询数据比较慢,添加和删除数据比较快(基于链表数据结构)

Vector——Vector已经不建议使用,Vector中的方法都是同步的,效率慢,已经被ArrayList取代

Stack——继承Vector实现的栈,栈结构是先进后出,但已被LinkedList取代

5、

  1. Set是一个无序集合,既存入集合的顺序和取出的顺序不一致
  1. Set集合中元素不重复

    3.TreeSet底层由TreeMap实现。可排序,默认自然升序。

6、Map集合

Map用于保存具有映射关系的数据,因此Map集合里保存两组值。

一组值用于保存key,一组值用于保存value key~value之间存在单向一对一关系,通过指定key可以找到唯一的value值

key和value都可以是任何引用类型对象 允许存在value为null,但是只允许存在一个key为null

  1. HashMap类

【特点】

key无序不可重复
底层是哈希表
           

1

2

【哈希表实现原理】

HashMap实际上是一个"链表的数组"的数据结构,每个元素存放链表头结点的数组,即数组和链表的结合体。

当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

只有相同的hash值的两个值才会被放到数组中的同一个位置上形成链表。

如果这两个Entry的key通过equals比较返回true,新添加Entry的value将覆盖集合中原有Entry的value,但key不会覆盖

HashMap实际上是一个"链表的数组"的数据结构,每个元素存放链表头结点的数组,即数组和链表的结合体。

当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

只有相同的hash值的两个值才会被放到数组中的同一个位置上形成链表。

如果这两个Entry的key通过equals比较返回true,新添加Entry的value将覆盖集合中原有Entry的value,但key不会覆盖。

【总结】

HashMap中key的hashCode值决定了<k,v>键值对组成的entry在哈希表中的存放位置。

HashMap中key通过equals()比较,确定是覆盖key对应的value值还是在链表中添加新的entry。

综合前两条,需要重写hashCode()和equals()方法。

  1. HashSet底层由HashMap实现
  2. 无序不可重复

java.util.LinkedList集合 implements List接口 * 特点: *

1.底层是一个链表结构,查询慢;增删快 * 2.里面包含了大量操作首尾元素的方法 * 注意:使用LinkedList集合特有的方法,不能使用多态

  • java.util.Set接口 extends Collection接口 * 特点: * 1.不允许存储重复的元素 *

    2.没有索引,也没有带索引的方法 * java.util.HashSet类 implements Set接口 * 特点: * 1.是一个无序集合 * 2.底层是一个哈希表结构(查询速度非常快)

  • java.util.LinkedHashSet集合 extends HashSet集合 * 特点: *

    底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序 * *

    java.util.LinkedHashMap<K,V> extends HashMap<K,V> * 底层原理: *

    哈希表+链表(有序

  • java.util.Hashtable<K,V>集合 implements Map<K,V>接口 * *

    Hashtable:底层是一个哈希表,是一个线程安全的集合,单线程集合,速度慢 *

    HashMap:底层是一个哈希表,是一个线程不安全的集合,多线程集合,速度快 * *

    HashMap集合(之前学过的所有集合):可以存储null值、null键 * Hashtable集合:不可以存储null值、null键