管弦丝竹,余音袅袅


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 搜索

hibernate学习笔记

发表于 2017-05-11 | 分类于 hibernate | 0 comments

hibernate学习笔记

1.Hibernate里不对对象或集合对象重载toString方法,不然编译错误 。Stackoverflow错误 栈溢出

2.什么是维护关联关系:
一对多时候 设置外键的值
多对多时候 就是插入或删除中间表的记录

3对象的状态:

临时状态:
与数据库没有对应,跟Session没有关联。
一般是新new出的对象。

持久化状态:
对象在Session的管理之中,最终会有对应的数据库记录。
特点:
a,有OID
b,对对象的修改会同步到数据库。

游离状态:
数据库中有对应记录,但对象不在Session管理之中。
修改此状态对象时数据库不会有变化。

4.主键id的生成

<id name="id">




5.数据库sql的四个级别:
读未提交 1 0001
读已提交 2 0010
可重复度 4 0100
串行化(不可并发) 8 1000

6.一对一:

外键约束 + 唯一性约束

比较特殊只有有外键方的一方才能维护关联关系
所有解除关联是,没外键的一方解除无效。

基于外键的一对一

基于主键的一对一



person
  1. 在having中不能使用列别名,order by 可以用

8.java中为什么要给类使用代理,有什么好处

http://www.iteye.com/problems/15304

9.懒加载:

也叫延迟加载,不是在执行获取操作时马上生成SQL,而是在第一次使用时生成SQL。
分成两种:
    类级别的:
        <class ... lazy="true/false">
    属性级别的:
        <set/list/map/bag ... lazy="...">
        <many-to-one ... lazy="...">
        <one-to-one ... lazy="...">
在使用懒加载特性时,可能会有LazyInitializationException异常:
    原因:   
        真正的去获取数据时,Session已经没有了。
    解决办法:
        方式一:让Session在真正加载后再关闭。
        方式二:或是在Sessoin关闭前执行Hibernate.initialize(department.getEmployees());

extra策略:(加强懒加载) 注意!!!
与 lazy=“true” 类似. 主要区别是增强延迟检索策略能进一步延迟 Customer 对象的 orders 集合代理实例的初始化时机:
• 当程序第一次访问 orders 属性的 iterator() 方法时, 会导致 orders 集合代理类实例的初始化
• 当程序第一次访问 order 属性的 size(), contains() 和 isEmpty() 方法时, Hibernate 不会初始化 orders 集合类的实例,
仅通过特定的 select 语句查询必要的信息, 不会检索所有的 Order 对象

10.缓存是按id来查询的! (使用id获得对象 才有效)
一级缓存 相对于类对象,
二级缓存 相对于sessionfactory,应用级别的缓存。在session查询数据库前的缓存

注意!!!
对于集合里的二级缓存,不仅要声明此时对象里的集合属性要二级缓存,而且集合里的对应类型对象也要声明是二级缓存。这样才能实现二级缓存的效果!
不然的话虽然第一次查询这个集合里的所有数据,第二次查询是集合里的对象所对应的属性还是要再按照其自身的id依次查询(生成对个sql语句),不好。

缓存一般使用在load和get方法
query.list()查询方法默认不使用缓存。就算hql语句后又where id=。。。都不行。
1.如果要使用query.list()那么要使用迭代器 iterator();不过有n+1次查询问题,不常用!!!
2.也可以使用 .setCacheable(true)// 是否使用查询缓存,需要在hibernate.cfg.xml中开启查询缓存才行(不过hql条件要一致)

1. select new list(p.name, p.address) from Person as p ;

select将选择出来的属性存入一个List对象中

select new ClassTest(p.name, p.address) from Person as p;
select将选择出来的属性封装成对象,前提是ClassTest支持p.name, p.address的构造函数,

select new map(p.name as personName) from Person as p ;
select将选中的表达式命名为别名,这种用法与new map()结合,选择出来的是Map结构,
以personName为key,将实际选择出来的值作为value

java的基本数据类型和引用类型

发表于 2017-05-10 | 分类于 java | 0 comments

java的基本数据类型和引用类型

基本类型:简单数据类型是不能简化的、内置的数据类型、由编程语言本身定义,它表示了真实的数字、字符和整数。
 引用数据类型:Java语言本身不支持C++中的结构(struct)或联合(union)数据类型,它的复合数据类型一般都是通过类或接口进行构造,类提供了捆绑数据和方法的方式,同时可以针对程序外部进行信息隐藏

一、8种基本基本数据类型(分布尔类型和数值类型)。

1、4种整型
byte 1字节 -128——127
short 2 字节 -32,768 —— 32,767
int 4 字节 -2,147,483,648 —— 2,147,483,647(超过20亿)
long 8 字节 -9,223,372,036,854,775,808——9,223,372,036854,775,807
注释:java中所有的数据类所占据的字节数量与平台无关,java也没有任何无符号类型
2、 2种浮点类型
float 4 字节 32位IEEE 754单精度(有效位数 6 – 7位)
double 8 字节 64位IEEE 754双精度(有效位数15位)
3、1种Unicode编码的字符单元
char 2 字节 整个Unicode字符集
4、1种真值类型
boolean 1 位 true或者false

##二、种引用类型
类class
接口interface
数组array

##三、Java数据类型在内存中的存储:
给变量赋值前需要先确定变量的类型,确定了变量的类型,即确定了数据需分配内存空间的大小,数据在内存的存储方式。
1)基本数据类型的存储原理:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,而Java语言里面八种数据类型是这种存储模型;

2)引用类型的存储原理:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”是存储在有序的内存栈上的(存储对象地址),而对象本身(实例化后的对象)的值存储在内存堆上的;

区别:基本数据类型和引用类型的区别主要在于基本数据类型是分配在栈上的,而引用类型是分配在堆上的()(需要java中的栈、堆概念)

四、“==”和equal()对数据类型的分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
eg1:定义两个String对象(String不是基本数据类型)
//String是一个特殊的包装类数据。可以用以下两种方式创建:
//String str = new String(“abc”);String str = “abc”;
String a="abc";//栈中的a引用变量指向JVM运行时数据区区域方法区的常量池中的“abc”。
String b="abc";//栈中的b引用变量也指向方法区中的常量池中的"abc",和a指向的地址一样
String c = new String("abc");
//new一个新的String实例对象,引用变量c指向实例化对象new String("abc")的地址,该实例化对象存储在堆中[ **实际该地址指针(地址存在堆中)指向此对象类型数据(存在方法区中数据值)即abc**],这和存在常量池的“abc”值得地址不一样。
if(a==b){
System.out.println("a==b");
}else{
System.out.println("a!=b");}
System.out.printLn(a==c)

结果:
程序输出a==b
flase
原因:a和b引用变量指向的地址的是相同的,a==b比较的是两个引用变量所指向的地址。
a和c引用变量指向的地址的是不相同的,a指向常量区中的abc,c指向新开辟在堆内存中的String对象实例中的abc实例对象中数据值得地址;两个地址不同,==比较返回false。
images
images

images
参考
eg2:定义两个基本数据类型

1
2
3
4
5
6
7
8
int a=4; //栈中的a引用变量指向方法区中的常量池中的4
int b=4; //栈中的b引用变量也指向方法区中的常量池中的4
if(a==b){
System.out.println("a==b");
}
else{
System.out.println("a!=b");
}

结果:
输出:a==b
原因:a和b指向同一个常量区中常量4的地址。==比较两者地址相等。

不管是引用类型或基本数据类型使用“==”比较,实际上他们都先在栈空间创建了一个各自的变量引用如int a=1 或String b 等,并比较他们指向的地址的值;
如果给基本数据类型赋值,实际是先将在方法区中的常量区中查找是否存在值1的地址(该值有一个唯一的地址),如果存在则将a指向该地址;不存在那么在常量区新建一个值为1的空间,并将该值得地址赋值给a。如果重新给a赋值如:a = 2,同理将a指向的地址改为常量区中值为2的地址。注意 int c =1,代表a和b指向同一个地址(常量区中1的地址)。
如果使用new 实例化对象,对象的引用变量指向的是在堆中该对象实例化的对象地址;
equal()方法比较的是引用变量指向地址最终指向的值。

java集合汇总

发表于 2017-05-09 | 分类于 java | 0 comments

java集合汇总

几个主要结合的主要关系:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap

一、集合与数组

数组:是用来存储对象(存储对象的引用,java的基本数据类型和引用类型)和基本数据类型的一种容器,但是数组的长度在创建时候已经固定,不适合在对象数量未知的情况下使用。

集合:通俗的讲集合是一个存放数据的容器,准确的讲集合是一个 存放数据对象引用的容器,并非对象本身。(只能存储对象,对象类型可以不一样),集合长度可变,可在多数情况下使用。
注意:
集合存放的都是对象的引用,那些看似存放着基本数据类型其实已经通过java自动装,拆箱操作装成了相应的对象。

1
2
3
List list =new ArrayList();
list.add(12);
System.out.println(list.get(0).getClass().getName());//Integer类型 自动装、拆箱

二、层次关系

如图所示:图中,实线边框的是实现类,折线边框的是抽象类,而点线边框的是接口:

##集合框架图:
image

Collection接口是集合类的根接口,Java中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个接口,就是Set和List。Set中不能包含重复的元素(set集合的去重原理)。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。

Map是Java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value。

Iterator(迭代接口),所有的集合类,都实现了Iterator接口,所以不论Collection实际类型是哪一个都支持iterator()的方法,该方法返回一个迭代子。这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
1.hasNext()是否还有下一个元素。
2.next()返回下一个元素。
3.remove()删除当前元素。
典型使用:

1
2
3
4
Iterator it = collection.iterator(); // 获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元素
    }

注意:
Collection collection = new ArrayList();(这样写的好处在于,以后如果要引用不同的集合,可以省略很多麻烦。因为都是用Collection接口里的方法,java多态的提现,向上转型)
容器类对象在调用remove,contains等方法时需要比较对象是否相等地,这会涉及到对象类型的equals方法和hashcode方法。即,相等的对象应该有相等的hashcode.当然,如果是自定义的类型,需要重写这两个方法

三、几种重要的集合接口和类简介

1、List(有序、可重复)
List 接口继承了 Collection 接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
List 接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器
注意:尽管列表允许把自身作为元素包含在内,但建议要特别小心:在这样的列表上,equals 和 hashCode 方法不再是定义良好的。

2、Set(无序、不能重复)
Set接口同样是Collection接口的一个子接口,它表示数学意义上的集合概念。Set中不包含重复的元素,即Set中不存两个这样的元素e1和e2,使得e1.equals(e2)为true。由于Set接口提供的数据结构是数学意义上集合概念的抽象,因此它需要支持对象的添加、删除,而不需提供随机访问。故Set接口与Collection的接口相同。Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,set可以存入null和boolean型。

3、Map(键值对、键唯一、值不唯一)
Map 接口不是 Collection 接口的继承。而是从自己的用于维护键-值关联的接口层次结构入手。按定义,该接口描述了从不重复的键到值的映射。
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。

四、遍历
在类集中提供了以下四种的常见输出方式:
1)Iterator:迭代输出,是使用最多的输出方式。
2)ListIterator:是Iterator的子接口,专门用于输出List中的内容。
3)foreach输出:JDK1.5之后提供的新功能,可以输出数组或集合。
4)for循环
代码示例如下:

1
2
3
4
5
for的形式:for(int i=0;i<arr.size();i++){...}
foreach的形式: for(int i:arr){...}
iterator的形式:
Iterator it = arr.iterator();
while(it.hasNext()){ object o =it.next(); ...}

集中常用的对应实现类总结

五、(实现List集合接口)ArrayList、LinkedList,和Vector
ArrayList和LinkedList在用法上没有区别,但是在功能上还是有区别的。LinkedList经常用在增删操作较多而查询操作很少的情况下,ArrayList则相反。
即:ArrayList :读快改慢,动态数组
LinkedList:改快读慢,链表,队列,堆栈。
Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。

六、Set集合(HashSet和TreeSet)
HashSet:使用哈希表实现的,HashSet集合是无序的,可以存入null当只能存一个,存入的对象或数据唯一。
TresSet:使用二叉树实现,集合是有序且自动排列好的(默认升序排序)。可以通过实现Comparable接口,重写接口里面的
compareTo(Object obj)方法来自定义排序,该方法返回一个整数值。该集合不允许放入null值。
参考:TreeSet和HashSet的区别
注意:
HashSet 和 TreeSet 都实现 Cloneable 接口。
HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。

七、Map集合

实现类:HashMap、Hashtable、LinkedHashMap和TreeMap

HashMap
HashMap是最常用的Map(无序的),它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。因为键对象不可以重复,所以HashMap最多只允许一条记录的键为Null,允许多条记录的值为Null,是非同步的,效率高。

Hashtable
Hashtable与HashMap类似,是HashMap的线程安全版,它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,它继承自Dictionary类,不同的是它不允许记录的键或者值为null,同时效率较低。

ConcurrentHashMap
线程安全,并且锁分离。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

LinkedHashMap
LinkedHashMap保存了记录的插入顺序(有序的),在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的,在遍历的时候会比HashMap慢,有HashMap的全部特性。

TreeMap
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。不允许key值为空,非同步的;所以在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按顺序遍历键,那么TreeMap 会更好。
自定义排序例子:

1
2
3
4
5
6
7
8
9
TreeMap<Double,Object> rf = new TreeMap<Double,Object>(new Comparator(){
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub 重写compare方法,降序排列
Double a = (Double)o1;
Double b = (Double)o2;
return -a.compareTo(b);
}});

map的遍历

第一种:KeySet()
将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取key 。
取到的结果会乱序,是因为取得数据行主键的时候,使用了HashMap.keySet()方法,而这个方法返回的Set结果,里面的数据是乱序排放的。
典型用法如下:
Map map = new HashMap();
map.put(“key1”,”lisi1”);
map.put(“key2”,”lisi2”);
map.put(“key3”,”lisi3”);
map.put(“key4”,”lisi4”);
//先获取map集合的所有键的set集合,keyset()
Iterator it = map.keySet().iterator();
//获取迭代器
while(it.hasNext()){
Object key = it.next();
System.out.println(map.get(key));
}

第二种:entrySet()
Set> entrySet() //返回此映射中包含的映射关系的 Set 视图。(一个关系就是一个键-值对),就是把(key-value)作为一个整体一对一对地存放到Set集合当中的。Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()两种方法来取key和value。返回的是Entry接口。
典型用法如下:
Map map = new HashMap();
map.put(“key1”,”lisi1”);
map.put(“key2”,”lisi2”);
map.put(“key3”,”lisi3”);
map.put(“key4”,”lisi4”);
//将map集合中的映射关系取出,存入到set集合
Iterator it = map.entrySet().iterator();
while(it.hasNext()){
Entry e =(Entry) it.next();
System.out.println(“键”+e.getKey () + “的值为” + e.getValue());
}
推荐使用第二种方式,即entrySet()方法,效率较高。
对于keySet其实是遍历了2次,一次是转为iterator,一次就是从HashMap中取出key所对于的value。而entryset只是遍历了第一次,它把key和value都放到了entry中,所以快了。两种遍历的遍历时间相差还是很明显的。

八、主要实现类区别小结

Vector和ArrayList
1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。
2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%。如果在集合中使用数据量比较大的数据,用vector有一定的优势。
3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,如果频繁的访问数据,这个时候使用vector和arraylist都可以。而如果移动一个指定位置会导致后面的元素都发生移动,这个时候就应该考虑到使用linklist,因为它移动一个指定位置的数据时其它元素不移动。
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引数据快,插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快。

Arraylist和linkedlist
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

HashMap与TreeMap
1、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
2、在Map 中插入、删除和定位元素,HashMap是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。
两个map中的元素一样,但顺序不一样,导致hashCode()不一样。
同样做测试:
在HashMap中,同样的值的map,顺序不同,equals时,false;
而在treeMap中,同样的值的map,顺序不同,equals时,true,说明,treeMap在equals()时是整理了顺序了的。

HashTable与HashMap
1、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的。
2、HashMap允许存在一个为null的key,多个为null的value 。
3、hashtable的key和value都不允许为null。

##面试小结
Java集合框架是最常被问到的Java面试问题,要理解Java技术强大特性就有必要掌握集合框架。这里有一些实用问题,常在核心Java面试中问到。
  1、什么是Java集合API
  Java集合框架API是用来表示和操作集合的统一框架,它包含接口、实现类、以及帮助程序员完成一些编程的算法。简言之,API在上层完成以下几件事:
  ● 编程更加省力,提高城程序速度和代码质量
  ● 非关联的API提高互操作性
  ● 节省学习使用新API成本
  ● 节省设计新API的时间
  ● 鼓励、促进软件重用
  具体来说,有6个集合接口,最基本的是Collection接口,由三个接口Set、List、SortedSet继承,另外两个接口是Map、SortedMap,这两个接口不继承Collection,表示映射而不是真正的集合。
  2、什么是Iterator
  一些集合类提供了内容遍历的功能,通过java.util.Iterator接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用 Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合本省。
  3、Iterator与ListIterator有什么区别?
  Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。
  4、什么是HaspMap和Map?
  Map是接口,Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。
  5、HashMap与HashTable有什么区别?对比Hashtable VS HashMap
  两者都是用key-value方式获取数据。Hashtable是原始集合类之一(也称作遗留类)。HashMap作为新集合框架的一部分在Java2的1.2版本中加入。它们之间有一下区别:
  ● HashMap和Hashtable大致是等同的,除了非同步和空值(HashMap允许null值作为key和value,而Hashtable不可以)。
  ● HashMap没法保证映射的顺序一直不变,但是作为HashMap的子类LinkedHashMap,如果想要预知的顺序迭代(默认按照插入顺序),你可以很轻易的置换为HashMap,如果使用Hashtable就没那么容易了。
  ● HashMap不是同步的,而Hashtable是同步的。
  ● 迭代HashMap采用快速失败机制,而Hashtable不是,所以这是设计的考虑点。
  6、在Hashtable上下文中同步是什么意思?
  同步意味着在一个时间点只能有一个线程可以修改哈希表,任何线程在执行hashtable的更新操作前需要获取对象锁,其他线程等待锁的释放。
  7、什么叫做快速失败特性
  从高级别层次来说快速失败是一个系统或软件对于其故障做出的响应。一个快速失败系统设计用来即时报告可能会导致失败的任何故障情况,它通常用来停止正常的操作而不是尝试继续做可能有缺陷的工作。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。如果一个iterator在集合对象上创建了,其它线程欲“结构化”的修改该集合对象,并发修改异常 (ConcurrentModificationException) 抛出。
  8、怎样使Hashmap同步?
  HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。
  9、什么时候使用Hashtable,什么时候使用HashMap
  基本的不同点是Hashtable同步HashMap不是的,所以无论什么时候有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。
  如果在将来有一种可能—你需要按顺序获得键值对的方案时,HashMap是一个很好的选择,因为有HashMap的一个子类 LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说HashMap更灵活。

  10、为什么Vector类认为是废弃的或者是非官方地不推荐使用?或者说为什么我们应该一直使用ArrayList而不是Vector

  你应该使用ArrayList而不是Vector是因为默认情况下你是非同步访问的,Vector同步了每个方法,你几乎从不要那样做,通常有想要同步的是整个操作序列。同步单个的操作也不安全(如果你迭代一个Vector,你还是要加锁,以避免其它线程在同一时刻改变集合).而且效率更慢。当然同样有锁的开销即使你不需要,这是个很糟糕的方法在默认情况下同步访问。你可以一直使用Collections.sychronizedList来装饰一个集合。

  事实上Vector结合了“可变数组”的集合和同步每个操作的实现。这是另外一个设计上的缺陷。Vector还有些遗留的方法在枚举和元素获取的方法,这些方法不同于List接口,如果这些方法在代码中程序员更趋向于想用它。尽管枚举速度更快,但是他们不能检查如果集合在迭代的时候修改了,这样将导致问题。尽管以上诸多原因,Oracle也从没宣称过要废弃Vector。

###主要参考学习

  • Java集合类详解
  • JAVA集合类汇总

java编译原理了解

发表于 2017-05-08 | 分类于 java | 0 comments

java编译原理

java源代码(符合语言规范)–>javac–>.class(二进制文件)–>jvm–>机器语言(不同平台不同种类)

语义分析器、语法分析器、语义分析器、代码生成器
源码->token流->语法树->注解语法树->字节码
images

流程:

词法分析器:将源码转换为Token流
将源代码划分成一个个Token(找出java语言中的if,else,for等关键字)

语法分析器:将Token流转化为语法树
将上述的一个个Token组成一句句话(或者说成一句句代码块),检查这一句句话是不是符合Java语言规范(如if后面跟的是不是布尔判断表达式)

语义分析器:将语法树转化为注解语法树
将复杂的语法转化成简单的语法(eg.注解、foreach转化为for循环、去掉永不会用到的代码块)并做一些检查,添加一些代码(默认构造器)

代码生成器:将注解语法树转化为字节码(即将一个数据结构转化成另一个数据结构)

ps:要获取javac编译器,可以通过OpenJDK来下载源码,可以自己编译javac的源码,也可以通过调用jdk的

学习参考
Javac编译原理
Java编译原理(有感)

java对象转型

发表于 2017-05-08 | 分类于 java | 0 comments

java对象转型 向上转型和向下转型

  • 什么是对象转型?
    对象转型是在继承的基础上而言的,对象类型转换主要包含向上转型和向下转型。继承是java面向对象的基本特征之一,是代码复用的一种机制,通过继承子类可以复用父类的方法等;如果父类的方法不满足子类的需求,子类可以通过重写父类的方法或者新增属于自己特性的方法对自身的功能加以扩展。

    • 1向上转型:
      子类引用的对象转换为父类类型称为向上转型。子类的对象转为父类对象,此处父类对象可以是接口。
      {eg:Annimal dog =new Dog();}
    • 2向下转型:
      父类引用的对象转换为子类类型称为向下转型。
      {eg:Dog dog =new Animal();//不安全的向下转型
      上述编译通过,但是运行时候报错,类型转换错误!
      正确操作:
      Annimal ad =new Dog();
      Dog dog = (Dog)ad;
      }
  • 向上转型注意:

    • 前者是一个向上转型,Animal dog 引用指向new Dog();子类对象当成父类对象,只能调用父类的成员,如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法(这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。(即子类重写父类方法,向上转型对象调用该方法,方法指向子类中重写的方法)
    • 向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Animal {
public void eat(){
System.out.println("animal eatting...");
}
}
class Bird extends Animal{
public void eat(){
System.out.println("bird eatting...");
}
public void fly(){
System.out.println("bird flying...");
}
}
class Main{
public static void main(String[] args) {
Animal b=new Bird(); //向上转型
b.eat();
b.fly(); //此处提示在Animal中没有定义fly方法。
}
  • 向下转型注意:
    情况一:如果父类引用的对象如果引用的是指向的子类对象(即先向上转型),那么在向下转型的过程中是安全的。也就是编译是不会出错误的。此时对象可以调用子类所有的成员。
    情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。
1
2
3
4
5
6
7
8
9
10
11
12
13
class Main{
public static void main(String[] args) {
Animal b=new Bird(); //先向上转型(父类引用对象指向子类对象)
Bird bird = (Bird) b;//向下转型,编译和运行都不报错
Animal a=new Animal(); //(父类引用对象指向父类本身对象)
Bird bird = (Bird) a;//不安全的向下转型,编译正常,运行报错(类型转换错误)
//解决方法 instance of
if(a instanceof Bird){
Bird bird=(Bird) a;
bird.eat();
bird.fly();
}
}
  • 总结:
    1、父类引用可以指向子类对象,子类引用不能指向父类对象。
    2、把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。
    3、把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。
    4、upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效 。
    5、向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。

参考:夜雨阑珊

Let Your Heart Hold Fast

发表于 2017-04-16 | 分类于 music | 0 comments


Let Your Heart Hold Fast

All my days are spent
那飞速逝去的时日
All my cards are dealt
那已经确定的命运
Oh ,the descolation grows
悲凉无尽蔓延心脏
Every inch revealed
心脏每一寸
As my heart is pierced
都被刺穿
Oh,my soul is now exposed
灵魂彻底暴露
In the ocean deep
穿过深邃的海洋
In the canyons steep
越过险峻的峡谷
Walls of granite here I stand
我立在岩石之上
All my desperate calls
我所有绝望的呼唤
Rcho off the walls
在墙间回荡
Back and forth;then back again
久久不息
To believe I walk alone
相信自己能踽踽独行
Is a lie that I’ve been told
这是别人告诉我的谎言
So let your heart hold fast
所以不要灰心丧气
For this soon shall pass
因为一切都将成为过去
Like the high tide takes the sand
就像沙子会被海潮带走
Oh,Oh,Oh,Oh,!
哦~
Oh,Oh,Oh,Oh,!
哦~
Oh,Oh,Oh,Oh,Oh!
哦~
Oh,Oh,Oh,Oh,!
哦~
Oh,Oh,Oh,Oh,!
哦~
Oh,Oh,Oh,Oh,Oh!
哦~
At the bitter end
在痛苦的最后
Salt and liquid blend
泪水涌出
From the corner of eyes
从我的眼角滑落
All the miles wrecked
蹒跚走过的所有路
Every broken step
艰难走过的每一步
Always searching,always blind
一直在盲目的寻找
Never fear!No!Never fear!
不要畏惧!不要畏惧!
Never fear!No! Never fear!
永不畏惧!永不畏惧!
So let your heart hold fast
所以不要灰心丧气
For this soon shall pass
因为一切将成为过去
There’s another hill ahead
前方将是人生的另一座高峰


> 这世上总有很多我们无法掌控的事情,就像我想你一样,总是那么的不经意间。

flask get/post参数获取

发表于 2017-03-22 | 分类于 flask | 0 comments

flask 使用笔记

获得get和post 提交的参数

post 提交参数获取
request.form[‘xxx’] 其类型为:ImmutableMultiDict

1
2
3
4
5
6
@app.route("/deleteInfo", methods=['post'])
@allow_cross_domain
def delete_info():
print(type(request.form))
# < class 'werkzeug.datastructures.ImmutableMultiDict'>
_id = request.form["_id"]

get 提交参数获取

1
2
3
4
@app.route('/queryDetl')
@allow_cross_domain
def query_detail():
_id = request.args.get("_id")

解决Flask 跨域请求问题

发表于 2017-03-21 | 分类于 python | 0 comments

python flask 跨域访问装饰器实现

现在大多数的web项目都已经是前后端分离;一般纯的api接口需要考虑跨域访问问题 下面是简单的跨域访问装饰器在flask中的实现(其他语言web项目跨域处理方法类似)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from functools import wraps
from flask import make_response
def allow_cross_domain(fun):
@wraps(fun)
def wrapper_fun(*args, **kwargs):
rst = make_response(fun(*args, **kwargs))
rst.headers['Access-Control-Allow-Origin'] = '*'
rst.headers['Access-Control-Allow-Methods'] = 'PUT,GET,POST,DELETE'
allow_headers = "Referer,Accept,Origin,User-Agent"
rst.headers['Access-Control-Allow-Headers'] = allow_headers
return rst
return wrapper_fun
@app.route('/hosts/')
@allow_cross_domain
def domains():
pass

my first hexo

发表于 2017-03-20 | 0 comments

hello glinlf and hexo!

Hello World

发表于 2017-03-19 | 分类于 搭建博客 | 0 comments

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

123
glinlf

glinlf

心之所向 步履维艰

24 日志
11 分类
34 标签
© 2017 glinlf
由 Hexo 强力驱动
主题 - NexT.Pisces