总结源于海子博客http://www.cnblogs.com/dolphin0520/html
一、在class文件中有一部分来存储编译期间生成的字面常量以及符号引用,这部分叫作class文件常量池,在运行期间对应着方法区的运行时常量池。java
(1)String str1 = "hello world";和String str2= "hello world";都在编译期间生成了字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(固然只保存了一份)。经过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,若是存在,则直接将引用指向已经存在的字面常量; 不然在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。git
(2)String str = new String("hello world")经过new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。所以经过new来建立对象,建立出的必定是不一样的对象,即便字符串的内容是相同的。该段代码执行过程和类的加载过程是有区别的。在类加载的过程当中,确实在运行时常量池中建立了一个"hello world"对象,而在代码执行过程当中确实只建立了一个String对象,即在堆上建立了"hello world"对象。github
(3)String str = new String("hello"); str+="java";这段代码涉及(非建立)5个对象,首先,“hello”在堆和常量池各一个;其次,“java”在常量池有一个;最后,“helloJava”在堆和常量池各一个。第一次出现字符串直接量时会在池中建立一个新的,以后出现就不会建立了,而是直接把引用指向第一次建立的对象。但对于new出来的对象,不管怎样赋值,new一次在运行期建立一次(在堆中),不会考虑以前是否已经已存在相同的。并且,字符串是不可追加的,因此每次使用链接符号其实至关于先产生一个常量,而后再赋给引用,原来指向的串就成垃圾被回收了。算法
(4)String str1="java";//指向字符串常量池 String str2="blog";//指向字符串常量池 String s = str1+str2; +运算符会在堆中创建起两个String对象,这两个对象的值分别是“java”,"blog",也就是说从字符串常量池中复制这两个值,而后在堆中建立两个对象。而后再创建对象s,而后将“javablog”的堆地址赋给s. 这句话共建立了3个String对象。json
二、Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3;
api
Integer e = 321; Integer f = 321; Long g = 3L; Long h = 2L;数组
System.out.println(c==d);//true缓存
System.out.println(e==f);//falseiphone
System.out.println(c==(a+b));//true
System.out.println(c.equals(a+b));//true
System.out.println(g==(a+b));//true
System.out.println(g.equals(a+b));//false
System.out.println(g.equals(a+h));//true
当 "=="运算符的两个操做数都是 包装器类型的引用,则是比较指向的是不是同一个对象,而若是其中有一个操做数是表达式(即包含算术运算)
则比较的是数值
(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte, Short, Integer, Long, Character, Boolean, 另外两种浮点数类型(Float、Double)的包装类则没有实现。另外Byte, Short, Integer, Long, Character这5种整型的包装类也只在大于等于-128而且小于等于127时才使用常量池,也即对象不负责建立和管理大于127的这些类的对象。
mvn install:install-file //mvn 命令
-Dfile=sojson-demo.jar //要添加的包
-DgroupId=com.sojson //pom文件对应的groupId
-DartifactId=com.sojson.demo //pom文件对应得artifactId
-Dversion=1.0 //添加包的版本
-Dpackaging=jar
public ∨ ∨ ∨ ∨
protect ∨ ∨ ∨ ×
default ∨ ∨ × ×
private ∨ × × ×
(10)update ft_airport set ft_airport.airport_name=REPLACE(airport_name,'机场','');
(11)Java8 时间日期api https://lw900925.github.io/java/java8-newtime-api.html
(12)分布式与集群的区别 http://blog.csdn.net/javaloveiphone/article/details/52368291
(13)kafka http://blog.csdn.net/tangdong3415/article/details/53432166
(14)Windows环境下的监控工具
jvisualvm.exe在JDK安装目录下的bin目录下面,双击便可打开。
MemoryAnalyzer.exe。
(15)this表明当前对象。
static是不容许用来修饰局部变量。
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”! 对于变量,表示一旦给值就不可修改,而且经过类名能够访问。对于方法,表示不可覆盖,而且能够经过类名直接访问。
public class Test { Person person = new Person("Test"); static{ System.out.println("test static"); } public Test() { System.out.println("test constructor"); } public static void main(String[] args) { new MyClass(); } } class Person{ static{ System.out.println("person static"); } public Person(String str) { System.out.println("person "+str); } } class MyClass extends Test { Person person = new Person("MyClass"); static{ System.out.println("myclass static"); } public MyClass() { System.out.println("myclass constructor"); } }
结果为:
test static myclass static person static person Test test constructor person MyClass myclass constructor
在执行开始,先要寻找到main方法,由于main方法是程序的入口,可是在执行main方法以前,必须先加载Test类,所以会执行Test类中的static块。(注意:若是main方法在MyClass类中,则先会加载其父类Test,执行Test类中的static块,再加载MyClass类,执行MyClass类中的static代码块)接着执行new MyClass(),而MyClass类尚未被加载,所以须要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,可是因为Test类已经被加载了,因此只须要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完以后,就经过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,所以会执行Test中的Person person = new Person(),而Person类尚未被加载过,所以会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,而后就来初始化自身了,所以会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。
第一点,全部的类都会优先加载基类
第二点,静态成员的初始化优先
第三点,成员初始化后,才会执行构造方法
第四点,静态成员的初始化与静态块的执行,发生在类加载的时候。
第五点,类对象的建立以及静态块的访问,都会触发类的加载。
五、对于子类能够继承的父类成员变量,若是在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。若是要在子类中访问父类中同名成员变量,须要使用super关键字来进行引用。对于子类能够继承的父类成员方法,若是在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。若是要在子类中访问父类中同名成员方法,须要使用super关键字来进行引用。注意:隐藏和覆盖是不一样的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。
public class Test { public static void main(String[] args) { Shape shape = new Circle(); System.out.println(shape.name); //隐藏了子类 shape.printType(); //被子类覆盖 shape.printName(); //隐藏了子类 } } class Shape { public String name = "shape"; public Shape(){ System.out.println("shape constructor"); } public void printType() { System.out.println("this is shape"); } public static void printName() { System.out.println("shape"); } } class Circle extends Shape { public String name = "circle"; public Circle() { System.out.println("circle constructor"); } public void printType() { System.out.println("this is circle"); } public static void printName() { System.out.println("circle"); } }
结果为:
shape constructor circle constructor shape this is circle shape
六、接口与抽象类
抽象类:[ public ] abstract class ClassName {
1)抽象方法必须为public或者protected(由于若是为private,则不能被子类继承,子类便没法实现该方法),缺省状况下默认为public。
2)抽象类不能用来建立对象;
3)若是一个类继承于一个抽象类,则子类必须实现父类的抽象方法。若是子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。
在其余方面,抽象类和普通的类并无区别。
接口:[ public ] interface InterfaceName {
[ public static final ] String MSG = "hello",//全局常量
[ public abstract ] void print();//抽象方法
}
2)方法会被隐式地指定为public abstract方法
语法层面区别:
1)抽象类能够提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量能够是各类类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类能够有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却能够实现多个接口。
设计层面上的区别:
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类总体进行抽象,包括属性、行为,可是接口倒是对类局部(行为)进行抽象。若是一个类继承了某个抽象类,则子类一定是抽象类的种类,而接口实现则是有没有、具有不具有的关系,好比鸟是否能飞(或者是否具有飞行这个特色),能飞行则能够实现这个接口,不能飞行就不实现这个接口。
2)设计层面不一样,抽象类做为不少子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。对于抽象类,若是须要添加新的方法,能够直接在抽象类中添加具体的实现,子类能够不进行变动;而对于接口则不行,若是接口进行了变动,则全部实现这个接口的类都必须进行相应的改动。
七、建立成员内部类对象的通常方式
public class Test { public static void main(String[] args) { //第一种方式: Outter outter = new Outter(); Outter.Inner inner = outter.new Inner(); //必须经过Outter对象来建立 //第二种方式: Outter.Inner inner1 = outter.getInnerInstance(); } } class Outter { private Inner inner = null; public Outter() { } public Inner getInnerInstance() { if(inner == null) inner = new Inner(); return inner; } class Inner { public Inner() { } } }
八、线程建立到消亡的状态
九、Lock和synchronized的选择
总结来讲,Lock和synchronized有如下几点不一样:
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,所以不会致使死锁现象发生;而Lock在发生异常时,若是没有主动经过unLock()去释放锁,则极可能形成死锁现象,所以使用Lock时须要在finally块中释放锁;
3)Lock可让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不可以响应中断;
4)经过Lock能够知道有没有成功获取锁,而synchronized却没法办到。
5)Lock能够提升多个线程进行读操做的效率。
在性能上来讲,若是竞争资源不激烈,二者的性能是差很少的,而当竞争资源很是激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。因此说,在具体使用时要根据适当状况选择。
十、nio读写文件
public static void main(String[] args) throws IOException { FileInputStream in = new FileInputStream("D:\\bbb.txt"); FileOutputStream on = new FileOutputStream("D:\\aaa.txt"); //为该文件输入流生成惟一的文件通道 FileChannel FileChannel channel = in.getChannel(); FileChannel fileChannel = on.getChannel(); //开辟一个长度为1024的字节缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); while(true){ //clear方法重设缓冲区,能够读新内容到buffer里 buffer.clear(); if (channel.read(buffer) == -1) { break; } System.out.println(new String(buffer.array(),"GBK")); //flip方法让缓冲区的数据输出到新的通道里面 buffer.flip(); fileChannel.write(buffer); } }
十一、return、continue、break
public static void main(String[] args) { for (int i = 0; i < 6; i++) { if (i==4) { return;//0 1 2 3 知足return条件后该循环体以及循环后的方法不往下执行 // break;//0 1 2 3 111 知足break条件后该循环终止,但循环后的方法仍往下执行 // continue;//0 1 2 3 5 111 仅知足continue条件的项不执行,循环体以及循环后的方法仍执行 } System.out.println(i); } System.out.println(111); }
十二、简单工厂模式
工厂方法模式
抽象工厂模式
http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html
在什么状况下应当使用抽象工厂模式
(1)一个系统不该当依赖于产品类实例如何被建立、组合和表达的细节,这对于全部形态的工厂模式都是重要的。
(2)这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
(3)同属于同一个产品族的产品是在一块儿使用的,这一约束必须在系统的设计中体现出来。(好比:Intel主板必须使用Intel CPU、Intel芯片组)
(4)系统提供一个产品类的库,全部的产品以一样的接口出现,从而使客户端不依赖于实现。
1三、成员变量与局部变量的区别:
一:在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法创建一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的缘由。在方法中声明的变量能够是基本类型的变量,也能够是引用类型的变量。
(1)当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在JAVA虚拟机栈中
(2)当声明的是引用变量时,所声明的变量(该变量其实是在方法中存储的是内存地址值)是放在JAVA虚拟机的栈中,该变量所指向的对象是放在堆类存中的。
二:在类中声明的变量是成员变量,也叫全局变量,放在堆中的(由于全局变量不会随着某个方法执行结束而销毁)。一样在类中声明的变量便可是基本类型的变量 也但是引用类型的变量
(1)当声明的是基本类型的变量其变量名及其值放在堆内存中的
(2)引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象。引用变量名和对应的对象仍然存储在相应的堆中
(1)定义的位置不一样
成员变量定义在类中,在整个类中均可以被访问。
局部变量只定义在局部范围内,如:函数内,语句内等。
(2)在内存中的位置不一样
成员变量存在于对象所在的堆内存中。
局部变量存在于栈内存中。
(3)生命周期不一样
成员变量随着对象的创建而创建,随着对象的消失而消失。
局部变量随着方法的运行而出现,随着方法的弹栈而消失。
(4)初始化不一样
成员变量无论程序有没有显式的进行初始化,加载时Java虚拟机都会先自动给它初始化为默认值。
局部变量声明以后,Java虚拟机就不会自动给它初始化为默认值,所以局部变量的使用必须先通过显式的初始化。
1四、静态变量与成员变量的区别:
(1)所属范围不一样
静态变量所属于类,成员变量所属于对象。
静态变量也称为:类变量 成员变量也称为:实例变量。
(2)调用不一样
静态变量能够被对象和类名调用(通常用类名调用)。
成员变量只能被对象调用。
(3)加载时期不一样
静态变量随着类的加载而加载。
成员变量随着对象的加载而加载。
(4)内存的存储区域不一样
静态变量存储在方法区。
成员变量存储在堆内存。
1五、摘录于http://www.cnblogs.com/xiaoxi/p/6428432.html
http://www.cnblogs.com/xiaoxi/p/6473480.html
(1)从Set集合元素不可重复性看hashCode()的做用
Set里面的元素是不能够重复的,那么如何作到?Set是根据equals()方法来判断两个元素是否相等的。比方说Set里面已经有1000个元素了,那么第1001个元素进来的时候,最多可能调用1000次equals方法,若是equals方法写得复杂,对比的东西特别多,那么效率会大大下降。使用HashCode就不同了,比方说HashSet,底层是基于HashMap实现的,先经过HashCode取一个模,这样一会儿就固定到某个位置了,若是这个位置上没有元素,那么就能够确定HashSet中一定没有和新添加的元素equals的元素,就能够直接存放了,都不须要比较;HashCode相等,再equals比较,没有相同的元素就存,有相同的元素就不存。若是原来的Set里面有相同的元素,只要HashCode的生成方式定义得好(不重复),无论Set里面原来有多少元素,只须要执行一次的equals就能够了。这样一来,实际调用equals方法的次数大大下降,提升了效率。
hashCode() 的做用是获取哈希码,也称为散列码;它其实是返回一个int整数。这个哈希码的做用是肯定该对象在哈希表中的索引位置。hashCode在上面扮演的角色为寻域(寻找某个对象在集合中区域位置)。hashCode能够将集合分红若干个区域,每一个对象均可以计算出他们的hash码,能够将hash码分组,每一个分组对应着某个存储区域,根据一个对象的hash码就能够肯定该对象所存储区域,这样就大大减小查询匹配元素的数量,提升了查询效率。
每一个Java类都包含hashCode() 函数。可是,仅仅当建立某个“类的散列表”(Java集合中本质是散列表的类,如HashMap,Hashtable,HashSet)时,该类的hashCode() 才有用(做用是:肯定该类的每个对象在散列表中的位置);其它状况下(例如,建立类的单个对象,或者建立类的对象数组等等),类的hashCode() 没有做用。
也就是说:hashCode() 在散列表中才有用,在其它状况下没用。在散列表中hashCode() 的做用是获取对象的散列码,进而肯定该对象在散列表中的位置。
(2)equals()的做用
equals() 的做用是 用来判断两个对象是否相等(即,是不是同一个对象)。
public boolean equals(Object obj) { return (this == obj); }
既然Object.java中定义了equals()方法,这就意味着全部的Java类都实现了equals()方法,全部的类均可以经过equals()去比较两个对象是否相等。 可是,咱们已经说过,使用默认的“equals()”方法,等价于“==”方法。所以,咱们一般会重写equals()方法:若两个对象的内容相等,则equals()方法返回true;不然,返回fasle。
下面根据“类是否覆盖equals()方法”,将它分为2类。
(01) 若某个类没有覆盖equals()方法,当它的经过equals()比较两个对象时,其实是比较两个对象是否是同一个对象。这时,等价于经过“==”去比较这两个对象。
(02) 咱们能够覆盖类的equals()方法,来让equals()经过其它方式比较两个对象是否相等。一般的作法是:若两个对象的内容相等,则equals()方法返回true;不然,返回fasle。
(3)hashCode()与equals()总结
1)hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中肯定对象的存储地址的;
2)若是两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode必定要相同;
3)若是对象的equals方法被重写,那么对象的hashCode也尽可能重写,而且产生hashCode使用的对象,必定要和equals方法中使用的一致,不然就会违反上面提到的第2点;
4)两个对象的hashCode相同,并不必定表示两个对象就相同,也就是不必定适用于equals(java.lang.Object) 方法,只可以说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。
hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。
例如内存中有这样的位置
0 1 2 3 4 5 6 7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,若是不用hashcode而任意存放,那么当查找时就须要到这八个位置里挨个去找,或者用二分法一类的算法。 但若是用hashcode那就会使效率提升不少。 咱们这个类中有个字段叫ID,那么咱们就定义咱们的hashcode为ID%8,而后把咱们的类存放在取得得余数那个位置。好比咱们的ID为9,9除8的余数为1,那么咱们就把该类存在1这个位置,若是ID是13,求得的余数是5,那么咱们就把该类放在5这个位置。这样,之后在查找该类时就能够经过ID 除 8求余数直接找到存放的位置了。 可是若是两个类有相同的hashcode怎么办那(咱们假设上面的类的ID不是惟一的),例如9除以8和17除以8的余数都是1,那么这是否是合法的,回答是:能够这样。那么如何判断呢?在这个时候就须要定义 equals了。 也就是说,咱们先经过 hashcode来判断两个类是否存放某个篮子里,但这个篮子里可能有不少类,那么咱们就须要再经过 equals 来在这个篮子里找到咱们要的类。
为何必需要重写hashcode方法,其实简单的说就是为了保证同一个对象,保证在equals相同的状况下hashcode值一定相同,若是重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(由于equal都是根据对象的特征进行重写的),但hashcode确实不相同的。