- 浏览: 3547868 次
- 性别:
- 来自: 大连
博客专栏
-
使用Titanium Mo...
浏览量:38135
-
Cordova 3.x入门...
浏览量:607253
-
常用Java开源Libra...
浏览量:682254
-
搭建 CentOS 6 服...
浏览量:89310
-
Spring Boot 入...
浏览量:401772
-
基于Spring Secu...
浏览量:69685
-
MQTT入门
浏览量:91690
文章分类
最新评论
-
afateg:
阿里云的图是怎么画出来的?用什么工具?
各云服务平台的架构图 -
cbn_1992:
博主,采用jdbctoken也就是数据库形式之后,反复点击获取 ...
Spring Security OAuth2 Provider 之 数据库存储 -
ipodao:
写的很是清楚了,我找到一份中文协议:https://mcxia ...
MQTT入门(6)- 主题Topics -
Cavani_cc:
还行
MQTT入门(6)- 主题Topics -
fexiong:
博主,能否提供完整源码用于学习?邮箱:2199611997@q ...
TensorFlow 之 构建人物识别系统
基础篇
(1)== vs equals()
==是操作符(可比较primitive),equals()是方法(继承自java.lang.Object,比较对象)
==比较对象在heap中的引用或内存中的位置(new一个对象会产生一个新的对象),equals()比较对象的状态和内容
==行为不可复写(Java不支持操作符重载),equals()可以覆写改变其比较行为
集合类一般使用compareTo()来比较对象
包装类用==比较时会先转成primitive后比较,所以要避免NPE;而且比较的是引用
Integer包装类对于-128到127有cache,所以结果会是true
(2)String literal vs new String()
new String("Java")会在heap中创建两个对象,一个String对象一个String常量。
literal会从String常量池中返回一个存在的对象(如果池中没有会默认创建一个自动调用intern()方法放入池中)
也可以自己调用intern()方法把任意对象放入池中:
String s1 = "Java";
String s2 = new String("Java");
s2 = s2.intern(); // 这里s1==s2为true
(3)String vs StringBuffer vs StringBuilder
String是immutable/final,StringBuffer是mutable
String通过+操作符连接,StringBuffer使用append()
String和StringBuffer不能强制转换,需要StringBuffer的toString()
StringBuffer同步且线程安全,StringBuilder不同步不线程安全
StringBuffer和StringBuilder都继承自AbstractStringBuilder
String/StringBuffer/StringBuilder内部都是用字符数组实现
StringBuffer/StringBuilder有初始容量capacity
(4)Interface vs Abstract Class
抽象类只能extend一个,接口可以implement多个
抽象类中可以定义非抽象方法,接口中不能定义非抽象方法(JDK8默认方法除外)
抽象类中即使没有抽象方法也可以标记为abstract
抽象类可以添加方法不影响子类,接口中添加方法需要修改所以它的实现类
抽象类适合代码重用,接口适合类型同一
接口没有方法实现更易于解耦
接口可以实现依赖注入
接口里的变量默认是public final
接口不可实例化,抽象类不可实例化但可以invoked
(5)Static vs Non Static class
类分为顶级类和嵌套内部类(还有特殊的匿名类)
顶级类不能被定义为static,嵌套内部类可以选择是否为static
嵌套内部类如果是static的话一般叫嵌套类,非static的叫内部类
嵌套类和内部类的创建方法不同:
Outer.Nested nested = new Outer.Nested();
Outer.Inner inner = new Outer().new Inner();
嵌套类可以被看做外部类的一个静态成员,可以在static方法中被使用
嵌套类不可以访问外部类的非static成员,内部类可以
(6)Primitive vs Reference variable
primitive变量有默认值
primitive变量存储值,reference变量存储对象在heap中的handle
primitive变量赋值是值的拷贝(互不影响),reference变量赋值是handle的拷贝(操作会影响另一方)
primitive变量使用==比较,reference变量使用equals()比较
primitive变量作为参数传递的是值,reference变量作为参数传递的是handle的拷贝
primitive变量参数的值在方法内被修改不影响原有值,reference变量参数修改handle不影响原有值但使用handle可以修改内部的值
primitive变量作为方法的返回值时返回的是值,返回reference变量时返回的是handle可以继续在方法外使用
primitive变量存储在stack,reference变量存储在heap
(7)Static vs Non Static method
static方法隶属于class,通过Class名直接调用(多用于工厂和单例),非static方法需要通过创建的对象来调用
static方法中不能访问非static变量
static方法不能被override
static方法多用于utility类
(8)transient vs volatile
transient变量不会被序列化(值是默认值)
volatile变量用于并发编程,被保存在单线程中,取值时也是从主线程中获取和当前线程栈无关(线程共享)
volatile经常用于实现单例来代替static final
transient和volatile只能用于变量不能用于方法或类
(9)volatile vs static
线程会缓存static变量
线程在操作static变量时是操作它们内部cache的local copy,不会影响其他线程
volatile变量只有一个main copy,各线程之间的更新会反映到其他线程
(10)throw vs throws
throw是在方法内部抛出异常,throws是在方法定义上标示该方法会抛出什么样的异常
throw一次只能抛出一个异常,throws可以通过逗号分隔标示多个异常
throw可以用于switch语句,throws只能用于方法定义处
throws只是标示给编译器用,并不会处理异常
方法内部抛出的需要checked的异常都要在方法定义处通过throws标示
不管是需要checked的或运行时异常都可以在throws标示,但运行时异常可以不标示
throws也可以只标示方法内部所有异常的父类
throw异常需要注意方法override引起的异常继承关系
(11)final vs finally vs finalize()
final用于变量/方法/类,finally用于try-catch,finalize()方法给GC调用
final变量不可修改,final方法不可override,final类不可继承
(12)Error vs Exception
常见Error:OutOfMemoryError
Error不需要try-catch即使catch了也无法解决,Exception异常catch后可做后续处理
RuntimeException表示的是程序代码的错误,Erro多为系统环境上致命错误
(13)Runtime Exception vs Checked Exception
常见Runtime异常:NullPointerException、ArrayIndexOutOfBoundException
常见Checked异常:ClassNotFoundException、IOException
Checked异常需要在调用处try-catch,Runtime异常不需要
Checked异常继承自Exception, Runtime异常继承自RuntimeException
自定义异常时需要注意标示异常是否为RuntimeException
(14)NoClassDefFoundError vs ClassNotFoundExcepiton
NoClassDefFoundError是Error不需要try-catch,ClassNotFoundException是Checked异常
NoClassDefFoundError出现在JVM或ClassLoader无法找到类(静态块初始化),ClassNotFoundException出现在程序动态加载类时
ClassNotFoundException多来自于Class.forName(),ClassLoader.findSystemClass(),ClassLoader.loadClass()
(15)Serializable vs Externalizable
Serializable是标记接口没有任何需要实现的方法,Externalizable继承自Serializable有两个需要实现的方法writeExternal()、readExternal()
Externalizable的子类JVM在序列化和反序列化对象时会调用writeExternal()、readExternal()
Serializable默认序列化所有类信息,Externalizable可以自定义序列化过程
Serializable序列化性能慢,可以通过使用transient或static
减少序列化字段来提高性能
Serializable由于字段的改变会变得不可维护
Externalizable可以处理transient变量或static变量
(16)Stack and Heap
stack存储本地变量和函数调用,heap存储对象
JVM启动可指定栈和堆得大小:stack(-Xss) heap(-Xms-Xmx)
stack空间不足时java.lang.StackOverFlowError
heap空间不足时java.lang.OutOfMemoryError: Java Heap Space
使用递归调用会让stack急剧变小
stack中的变量只能自己线程访问,stack中的对象所有线程都能访问
stack所需大小远小于heap
(17)Shallow Copy vs Deep Copy
浅拷贝:使用已知实例对新创建的实例的成员变量逐个赋值
深拷贝:不仅复制primitive变量值,还要为引用类型reference的成员变量创建新的实例
浅拷贝时,拷贝的对象和元对象不是100%隔离
浅拷贝时,任何修改元对象中引用类型变量的操作会反映到拷贝对象中,反之也是
默认clone()方法提供的是浅拷贝shallow copy,深拷贝需要override默认clone()方法
如果对象只有primitive变量,浅拷贝足够
(18)<? super T> vs <? extends T>
PECS: "Producer Extends, Consumer Super".
<? extends T> 表示类型的上界,可用于的返回类型限定,不能用于参数类型限定。
<? super T> 表示类型下界,表示参数化类型是此类型的父类型。可用于参数类型限定,不能用于返回类型限定。
集合篇
(1)Enumeration vs Iterator vs ListIterator
Iterator支持在遍历集合时删除元素,Enumeration不支持
Enumeration是JDK早期的遍历集合类的方法现在很少用
Enumeration是早期的类现在不是所有集合都支持Vector支持ArrayList不支持
Enumeration是一个只读接口用来遍历获取集合中的元素
Iterator在遍历集合时不允许其他线程修改集合中的元素
ListIterator是针对List类型集合的
Enumeration和Iterator是单向的,ListIterator是双向的
Enumeration的方法:xxx.elements(); hasMoreElement(),nextElement()
Iterator的方法:xxx.iterator(); hasNext(), next(), remove()
ListIterator的方法:xxx.listIterator(); hasNext(),next(),previous(),hasPrevious(),remove(),nextIndex(),previousIndex()
(2)Collection vs Collections
Collection是集合类的顶级接口,除过Map其他大部分实现在该接口
Collections是一个utility类,提供一些静态方法来处理集合类
(3)Comparator vs Comparable
Package不一样:java.lang.Comparable,java.util.Comparator
被排序的Object需要实现Comparable,新建一个类实现Comparator接口
Comparable实现的方法:compareTo(Object obj1) 比较当前对象和参数对象
Comparator实现的方法:compare(Object obj1, Object obj2) 比较参数的两个对象
compareTo(Object o1)返回值:正数-当前对象大于o1 0-相等 负数-当前对象小于o1
compare(Object o1,Object o2)返回值:正数-o1大于o2 0-相等 负数-o1小于o2
Collections.sort(List)调用Comparable比较元素
Collections.sort(List, Comparator)调用Comparator比较元素
Comparable:对Object只能写一套比较方法
Comparator:对Object可以写多个比较方法多次排序
(4)List vs Set vs Map
List有序可重复,可存多个null元素,主要实现:ArrayList, Vector, LinkedList
Set无序不可重复,只能存一个null元素,主要实现:HashSet, TreeSet, LinkedHashSet
Map键值对,键不可重复,键只有一个null,主要实现:HashMap, LinkedHashMap, Hashtable and TreeMap
(5)Array vs ArrayList
Array固定长度,ArrayList不固定长度(后台通过数组实现)
Array创建时需要指定长度,ArrayList不需要(JDK有默认初始容量并会自动扩容)
Array不支持泛型,ArrayList支持泛型
Array长度:arr.length; ArrayList大小:list.size();
ArrayList只能存对象不能存primitive变量(自动装箱除外)
(6)ArrayList vs LinkedList
ArrayList后台通过数组实现,LinkedList通过链表实现(嵌套类存储前后节点)
LinkedList不只是实现了List还实现了Deque(FIFO)。add(),poll()
添加元素:ArrayList-O(1) LinkedList-O(1)
删除元素:ArrayList-O(n) LinkedList-O(n/2)
获取元素:ArrayList-O(1) LinkedList-O(n/2)
(7)HashSet vs TreeSet
HashSet比TreeSet性能好
HashSet后台用Hashtable实现,TreeSet后台用红黑树实现
HashSet允许null,TreeSet不允许null
HashSet使用equals()比较对象,TreeSet使用compareTo()比较对象
(8)Fail-Safe vs Fail-Fast Iterator
安全失败(fail-safe)和快速失败(fail-fast)
fail-safe Iterator:集合元素被修改时不抛出异常
fail-fast Iterator:集合元素被修改时抛出异常ConcurrentModificationException
fail-safe iterator:遍历的是集合的一个副本
fail-fast iterator:遍历的是集合自身
fail-safe:CopyOnWriteArrayList,CopyOnWriteArraySet,ConcurrentHashMap
fail-fast:HashMap,ArrayList,HashSet
线程篇
(1)wait() vs sleep() vs yield()
Object.wait(),Thread.sleep(),Thread.yield()
wait(),wait(10),wait(10, 5); sleep(10),sleep(10, 5); yield()
wait()可通过notify()唤醒
wait()会释放对象锁,sleep(),yield()不会
wait()需要在同步块或同步方法中调用
yield()使当前线程停止时间是不定的
(2)start() vs run()
start()调用时会创建一个新线程,并且执行内部的run()方法
直接调用run()方法无法创建新线程,run()方法执行在当前线程里
start()方法不能调用多次,第二次会抛出IllegalStateException
(3)Thread vs Runnable interface
扩展继承Thread后就不能再继承其他类
Runnable标示该对象是一个Task可以被执行,执行还的通过Thread
(4)Callable vs Runnable
Callable会抛出checked异常,Runnable没有
Callable能在call()方法中返回操作结果,Runnable的run()方法不行
Callable可通过泛型传入返回类型
(5)Synchronized vs Concurrent Collections
都提供线程安全
Synchronized集合:Hashtable,Vector。Collections.synchronizedMap(),Collections.synchronizedList()
Concurrent集合:ConcurrentHashMap,CopyOnWriteArrayList
Synchronized集合比Concurrent集合性能慢
Synchronized集合锁整个对象,Concurrent集合会被分成多个segments锁其中一个segment
(6)Multi-Threading vs Multi-Tasking
multi-threading多个线程同时执行同一个程序或程序不同部分,multitasking并行执行不同的程序
multitasking有两种:基于进程process、基于线程thread。进程比线程开销跟大
(7)User thread vs Daemon thread
main thread里创建的线程默认都是user thread,通过setDaemon(true)能够是它变为daemon thread
daemon thread里边创建的线程也是daemon thread的
JVM在结束时需要等待user thread,但是不会等待daemon thread
JVM自身会创建一些daemon thread,比如GC
daemon thread的优先级更低
user thread可以被应用或线程自己关闭,JVM来终止daemon thread
不要再daemon thread里编写业务代码
设计篇
(1)Abstraction vs Encapsulation
Abstraction抽象:interface, abstract class
Encapsulation封裝:private, package-private, protected
(2)Overloading vs Overriding
Overload重载在编译期,Override重写在运行期
同一个类中overload方法,子类中override父类方法
可以overload静态方法,但不能override静态方法
private和final方法不能override,但可以overload
overload时需要修改方法的定义(参数表),override不需要
(3)Dependency Injection vs Factory Pattern
DI依赖注入需要第三方框架支持(比如Spring),工厂模式自己封装代码
DI松耦合设计,工厂模式耦合factory和object
DI框架替你常见管理实例,工厂通过getInstance()生产一个实例
DI更易于单体测试,更弹性灵活,但DI需要配置注入关系
(4)Singleton Pattern vs Static Class
单例提供的是Object,静态类提供的是方法
静态类性能更好
静态类方法不可override
静态类不便于测试
单例可以保持对象的状态等信息,静态类不可以
单例只在使用时加载(lazy load),静态类启动时加载
很多DI框架更容易支持单例
(5)Class vs Instance vs Object
Class的实例是对象。(An object is an instance of a class)
Class是用于创建对象的模板蓝图
Instance是类的一个唯一拷贝用于表现对象
Object拥有状态 state 和行为 behavior
JVM实际是先创建Instance后创建Object
具体参考这里
(6)Stack vs Heap
Heap存贮对象(JDK 7前String存在String Pool,之后也版本也存入Heap)
Stack存贮本地变量、方法定义、调用栈
所有线程共享Heap,各线程之间是不共享Stack的(本地变量是被线程隔离的)
创建thread后JVM会为其分配Stack
Heap的空间比Stack更大
可以指定Heap(-Xms-Xmx)和Stack(-Xss)的大小
Heap和Stack存储的数据结构是不一样的
其他
(1)trustStore vs keyStore
trustStore存储公钥和CA,keyStore存储私钥
trustStore验证证书,keyStore提供证书
创建SSLContext:trustStore-TrustManager(决定是否连接可信),keyStore-KeyManager(决定哪些连接在SSL握手时需要发到Server认证)
JRE默认trustStore保存在$JAVA_HOME/lib/security/cacerts
-Djavax.net.ssl.trustStore -Djavax.net.ssl.keyStore
-Djavax.net.ssl.trustStorePassword -Djavax.net.ssl.keyStorePassword
证书标准 :X.509
编码格式 :
PEM-encoded certificate (domain.pem) Apache和*NIX服务器
DER-encoded certificate (domain.der) Java和Windows服务器
文件扩展名 :
keystore.jks - Java的Keytool工具生成的密钥库,存储非对称密钥对(私钥+x509公钥证书),有时也叫xxxx.keystore
keytool -genkey -alias localhostkey -keystore localhost.keystore -storepass password -keypass password
domain.key - 存放一个公钥或者私钥,并非X.509证书
openssl genrsa -des3 -out domain.key 2048
domain.csr - 证书签名请求,存放一个公钥,并非X.509证书,生成证书时要提交给证书颁发机构
openssl req -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr
domain.crt - Self-Signed Certificate *NIX系统
openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
domain.cer - 证书文件,只有公钥
domain.p12 - 证书文件,包含公钥及私钥,PKCS12(domain.pfx)
(2)Type 1, 2, 3, 4 JDBC Driver
Type 1:非Java实现,最早的驱动连接Access,需要把JDBC请求转化为ODBC后链接,又叫JDBC ODBC bridge driver(性能差)
Type 2:非Java实现,JDBC直接通过native API和DB链接,需要native library比如ocijdbc11.dll
Type 3:Java Net实现,通过代理服务和DB链接,client-server-database,又叫Net protocol JDBC driver
Type 4:纯Java实现,通过native protocol直接和DB链接,驱动JAR文件中包含所有数据库的调用,又叫thin JDBC driver
(3)32-bit vs 64-bit
32位CPU寻址范围是2的32次方,大概4GB的RAM(留给应用的大概Linux:2GB,Windows:1.5GB)
64位系统各OS寻址范围不同Windows可达8TB
32位OS只能按照32位Java,64位OS可以安装32位Java或64位Java
64位需要heap的大小多于32位的30-50%(object headers、object references)
64位GC中断时间更长
.class不依赖于多少位的Java编译器(互通编译,互通使用)
整型值的上限和多少位没关系Integer.MAX_VAlUE = 2^31 - 1
(4)PATH vs CLASSPATH
- JAVA_HOME:
指向JDK安装目录,比如C:\Program Files\Java\jdk1.8.0_65
Java本身不使用,第三方应用比如Tomcat使用,因为运行需要JDK支持
- JRE_HOME:
指向JRE安装目录,比如C:\Program Files\Java\jdk1.8.0_65\jre
Java本身不使用,第三方应用比如Tomcat使用,因为运行需要JDK支持,Tomcat优先使用JRE_HOME
JDK安装后有两套相同的JRE:C:\Program Files\Java\jdk1.8.0_65\jre(供JDK附属工具用的)、C:\Program Files\Java\jre1.8.0_65
***javac XXX.java 等价于 java -cp "%JAVA_HOME%\lib\tools.jar" com.sun.tools.javac.Main XXX.java
***Tomcat早期版本需要JDK把jsp编译成servlet,现在已经内置Eclipse的ECJ来支持JSP。
- CLASSPATH:
JVM类加载器查找class的路径
Java6后支持通配符不用挨个指定jar,CLASSPATH="C:\Program Files\Java\jdk1.8.0_65\lib"
也可以通过-cp 或 -classpath参数指定后供javac和java命令使用
目前来说基本无需设置:JDK工具能自己查找到这些jar;IDE会为project设置不同classpath
***Eclipse有自己的编译器ECJ来编译代码不需要javac。
- PATH:
操作系统的默认环境变量,去查找javac和java等工具的位置
-rt.jar、dt.jar、tools.jar
rt.jar: JRE提供的所有类java.lang.String、java.util.ArrayList等,在$JAVA_HOME/jre/lib下。源代码:$JAVA_HOME/src.zip
dt.jar: 不要包含Swing的BeanInfo文件,在$JAVA_HOME/lib下。
tools.jar: JDK需要的工具集,javac、javadoc等需要调用这个jar,在$JAVA_HOME/lib下。
***这些文件都是提供给JVM使用的,一般不需要特别设置。而且这三个文件在JDK9会被删掉分到不同的文件!
(1)== vs equals()
==是操作符(可比较primitive),equals()是方法(继承自java.lang.Object,比较对象)
==比较对象在heap中的引用或内存中的位置(new一个对象会产生一个新的对象),equals()比较对象的状态和内容
==行为不可复写(Java不支持操作符重载),equals()可以覆写改变其比较行为
集合类一般使用compareTo()来比较对象
包装类用==比较时会先转成primitive后比较,所以要避免NPE;而且比较的是引用
Integer包装类对于-128到127有cache,所以结果会是true
(2)String literal vs new String()
new String("Java")会在heap中创建两个对象,一个String对象一个String常量。
literal会从String常量池中返回一个存在的对象(如果池中没有会默认创建一个自动调用intern()方法放入池中)
也可以自己调用intern()方法把任意对象放入池中:
String s1 = "Java";
String s2 = new String("Java");
s2 = s2.intern(); // 这里s1==s2为true
(3)String vs StringBuffer vs StringBuilder
String是immutable/final,StringBuffer是mutable
String通过+操作符连接,StringBuffer使用append()
String和StringBuffer不能强制转换,需要StringBuffer的toString()
StringBuffer同步且线程安全,StringBuilder不同步不线程安全
StringBuffer和StringBuilder都继承自AbstractStringBuilder
String/StringBuffer/StringBuilder内部都是用字符数组实现
StringBuffer/StringBuilder有初始容量capacity
(4)Interface vs Abstract Class
抽象类只能extend一个,接口可以implement多个
抽象类中可以定义非抽象方法,接口中不能定义非抽象方法(JDK8默认方法除外)
抽象类中即使没有抽象方法也可以标记为abstract
抽象类可以添加方法不影响子类,接口中添加方法需要修改所以它的实现类
抽象类适合代码重用,接口适合类型同一
接口没有方法实现更易于解耦
接口可以实现依赖注入
接口里的变量默认是public final
接口不可实例化,抽象类不可实例化但可以invoked
(5)Static vs Non Static class
类分为顶级类和嵌套内部类(还有特殊的匿名类)
顶级类不能被定义为static,嵌套内部类可以选择是否为static
嵌套内部类如果是static的话一般叫嵌套类,非static的叫内部类
嵌套类和内部类的创建方法不同:
Outer.Nested nested = new Outer.Nested();
Outer.Inner inner = new Outer().new Inner();
嵌套类可以被看做外部类的一个静态成员,可以在static方法中被使用
嵌套类不可以访问外部类的非static成员,内部类可以
(6)Primitive vs Reference variable
primitive变量有默认值
primitive变量存储值,reference变量存储对象在heap中的handle
primitive变量赋值是值的拷贝(互不影响),reference变量赋值是handle的拷贝(操作会影响另一方)
primitive变量使用==比较,reference变量使用equals()比较
primitive变量作为参数传递的是值,reference变量作为参数传递的是handle的拷贝
primitive变量参数的值在方法内被修改不影响原有值,reference变量参数修改handle不影响原有值但使用handle可以修改内部的值
primitive变量作为方法的返回值时返回的是值,返回reference变量时返回的是handle可以继续在方法外使用
primitive变量存储在stack,reference变量存储在heap
(7)Static vs Non Static method
static方法隶属于class,通过Class名直接调用(多用于工厂和单例),非static方法需要通过创建的对象来调用
static方法中不能访问非static变量
static方法不能被override
static方法多用于utility类
(8)transient vs volatile
transient变量不会被序列化(值是默认值)
volatile变量用于并发编程,被保存在单线程中,取值时也是从主线程中获取和当前线程栈无关(线程共享)
volatile经常用于实现单例来代替static final
transient和volatile只能用于变量不能用于方法或类
(9)volatile vs static
线程会缓存static变量
线程在操作static变量时是操作它们内部cache的local copy,不会影响其他线程
volatile变量只有一个main copy,各线程之间的更新会反映到其他线程
(10)throw vs throws
throw是在方法内部抛出异常,throws是在方法定义上标示该方法会抛出什么样的异常
throw一次只能抛出一个异常,throws可以通过逗号分隔标示多个异常
throw可以用于switch语句,throws只能用于方法定义处
throws只是标示给编译器用,并不会处理异常
方法内部抛出的需要checked的异常都要在方法定义处通过throws标示
不管是需要checked的或运行时异常都可以在throws标示,但运行时异常可以不标示
throws也可以只标示方法内部所有异常的父类
throw异常需要注意方法override引起的异常继承关系
(11)final vs finally vs finalize()
final用于变量/方法/类,finally用于try-catch,finalize()方法给GC调用
final变量不可修改,final方法不可override,final类不可继承
(12)Error vs Exception
常见Error:OutOfMemoryError
Error不需要try-catch即使catch了也无法解决,Exception异常catch后可做后续处理
RuntimeException表示的是程序代码的错误,Erro多为系统环境上致命错误
(13)Runtime Exception vs Checked Exception
常见Runtime异常:NullPointerException、ArrayIndexOutOfBoundException
常见Checked异常:ClassNotFoundException、IOException
Checked异常需要在调用处try-catch,Runtime异常不需要
Checked异常继承自Exception, Runtime异常继承自RuntimeException
自定义异常时需要注意标示异常是否为RuntimeException
(14)NoClassDefFoundError vs ClassNotFoundExcepiton
NoClassDefFoundError是Error不需要try-catch,ClassNotFoundException是Checked异常
NoClassDefFoundError出现在JVM或ClassLoader无法找到类(静态块初始化),ClassNotFoundException出现在程序动态加载类时
ClassNotFoundException多来自于Class.forName(),ClassLoader.findSystemClass(),ClassLoader.loadClass()
(15)Serializable vs Externalizable
Serializable是标记接口没有任何需要实现的方法,Externalizable继承自Serializable有两个需要实现的方法writeExternal()、readExternal()
Externalizable的子类JVM在序列化和反序列化对象时会调用writeExternal()、readExternal()
Serializable默认序列化所有类信息,Externalizable可以自定义序列化过程
Serializable序列化性能慢,可以通过使用transient或static
减少序列化字段来提高性能
Serializable由于字段的改变会变得不可维护
Externalizable可以处理transient变量或static变量
(16)Stack and Heap
stack存储本地变量和函数调用,heap存储对象
JVM启动可指定栈和堆得大小:stack(-Xss) heap(-Xms-Xmx)
stack空间不足时java.lang.StackOverFlowError
heap空间不足时java.lang.OutOfMemoryError: Java Heap Space
使用递归调用会让stack急剧变小
stack中的变量只能自己线程访问,stack中的对象所有线程都能访问
stack所需大小远小于heap
(17)Shallow Copy vs Deep Copy
浅拷贝:使用已知实例对新创建的实例的成员变量逐个赋值
深拷贝:不仅复制primitive变量值,还要为引用类型reference的成员变量创建新的实例
浅拷贝时,拷贝的对象和元对象不是100%隔离
浅拷贝时,任何修改元对象中引用类型变量的操作会反映到拷贝对象中,反之也是
默认clone()方法提供的是浅拷贝shallow copy,深拷贝需要override默认clone()方法
如果对象只有primitive变量,浅拷贝足够
(18)<? super T> vs <? extends T>
PECS: "Producer Extends, Consumer Super".
<? extends T> 表示类型的上界,可用于的返回类型限定,不能用于参数类型限定。
<? super T> 表示类型下界,表示参数化类型是此类型的父类型。可用于参数类型限定,不能用于返回类型限定。
List<? extends Number> foo1 = new ArrayList<Integer>(); // Integer extends Number List<? extends Number> foo2 = new ArrayList<Double>(); // Double extends Number Number a1 = foo1.get(0); Number a2 = foo2.get(0); foo1.add(1); // error foo2.add(1.5); // error
List<? super Integer> bar1 = new ArrayList<Number>(); // Number is a superclass of Integer List<? super Integer> bar2 = new ArrayList<Object>(); // Object is a superclass of Integer bar1.add(2); bar2.add(3); Object b1 = bar1.get(0); Object b2 = bar2.get(0);
集合篇
(1)Enumeration vs Iterator vs ListIterator
Iterator支持在遍历集合时删除元素,Enumeration不支持
Enumeration是JDK早期的遍历集合类的方法现在很少用
Enumeration是早期的类现在不是所有集合都支持Vector支持ArrayList不支持
Enumeration是一个只读接口用来遍历获取集合中的元素
Iterator在遍历集合时不允许其他线程修改集合中的元素
ListIterator是针对List类型集合的
Enumeration和Iterator是单向的,ListIterator是双向的
Enumeration的方法:xxx.elements(); hasMoreElement(),nextElement()
Iterator的方法:xxx.iterator(); hasNext(), next(), remove()
ListIterator的方法:xxx.listIterator(); hasNext(),next(),previous(),hasPrevious(),remove(),nextIndex(),previousIndex()
(2)Collection vs Collections
Collection是集合类的顶级接口,除过Map其他大部分实现在该接口
Collections是一个utility类,提供一些静态方法来处理集合类
(3)Comparator vs Comparable
Package不一样:java.lang.Comparable,java.util.Comparator
被排序的Object需要实现Comparable,新建一个类实现Comparator接口
Comparable实现的方法:compareTo(Object obj1) 比较当前对象和参数对象
Comparator实现的方法:compare(Object obj1, Object obj2) 比较参数的两个对象
compareTo(Object o1)返回值:正数-当前对象大于o1 0-相等 负数-当前对象小于o1
compare(Object o1,Object o2)返回值:正数-o1大于o2 0-相等 负数-o1小于o2
Collections.sort(List)调用Comparable比较元素
Collections.sort(List, Comparator)调用Comparator比较元素
Comparable:对Object只能写一套比较方法
Comparator:对Object可以写多个比较方法多次排序
(4)List vs Set vs Map
List有序可重复,可存多个null元素,主要实现:ArrayList, Vector, LinkedList
Set无序不可重复,只能存一个null元素,主要实现:HashSet, TreeSet, LinkedHashSet
Map键值对,键不可重复,键只有一个null,主要实现:HashMap, LinkedHashMap, Hashtable and TreeMap
(5)Array vs ArrayList
Array固定长度,ArrayList不固定长度(后台通过数组实现)
Array创建时需要指定长度,ArrayList不需要(JDK有默认初始容量并会自动扩容)
Array不支持泛型,ArrayList支持泛型
Array长度:arr.length; ArrayList大小:list.size();
ArrayList只能存对象不能存primitive变量(自动装箱除外)
(6)ArrayList vs LinkedList
ArrayList后台通过数组实现,LinkedList通过链表实现(嵌套类存储前后节点)
LinkedList不只是实现了List还实现了Deque(FIFO)。add(),poll()
添加元素:ArrayList-O(1) LinkedList-O(1)
删除元素:ArrayList-O(n) LinkedList-O(n/2)
获取元素:ArrayList-O(1) LinkedList-O(n/2)
(7)HashSet vs TreeSet
HashSet比TreeSet性能好
HashSet后台用Hashtable实现,TreeSet后台用红黑树实现
HashSet允许null,TreeSet不允许null
HashSet使用equals()比较对象,TreeSet使用compareTo()比较对象
(8)Fail-Safe vs Fail-Fast Iterator
安全失败(fail-safe)和快速失败(fail-fast)
fail-safe Iterator:集合元素被修改时不抛出异常
fail-fast Iterator:集合元素被修改时抛出异常ConcurrentModificationException
fail-safe iterator:遍历的是集合的一个副本
fail-fast iterator:遍历的是集合自身
fail-safe:CopyOnWriteArrayList,CopyOnWriteArraySet,ConcurrentHashMap
fail-fast:HashMap,ArrayList,HashSet
线程篇
(1)wait() vs sleep() vs yield()
Object.wait(),Thread.sleep(),Thread.yield()
wait(),wait(10),wait(10, 5); sleep(10),sleep(10, 5); yield()
wait()可通过notify()唤醒
wait()会释放对象锁,sleep(),yield()不会
wait()需要在同步块或同步方法中调用
yield()使当前线程停止时间是不定的
(2)start() vs run()
start()调用时会创建一个新线程,并且执行内部的run()方法
直接调用run()方法无法创建新线程,run()方法执行在当前线程里
start()方法不能调用多次,第二次会抛出IllegalStateException
(3)Thread vs Runnable interface
扩展继承Thread后就不能再继承其他类
Runnable标示该对象是一个Task可以被执行,执行还的通过Thread
(4)Callable vs Runnable
Callable会抛出checked异常,Runnable没有
Callable能在call()方法中返回操作结果,Runnable的run()方法不行
Callable可通过泛型传入返回类型
(5)Synchronized vs Concurrent Collections
都提供线程安全
Synchronized集合:Hashtable,Vector。Collections.synchronizedMap(),Collections.synchronizedList()
Concurrent集合:ConcurrentHashMap,CopyOnWriteArrayList
Synchronized集合比Concurrent集合性能慢
Synchronized集合锁整个对象,Concurrent集合会被分成多个segments锁其中一个segment
(6)Multi-Threading vs Multi-Tasking
multi-threading多个线程同时执行同一个程序或程序不同部分,multitasking并行执行不同的程序
multitasking有两种:基于进程process、基于线程thread。进程比线程开销跟大
(7)User thread vs Daemon thread
main thread里创建的线程默认都是user thread,通过setDaemon(true)能够是它变为daemon thread
daemon thread里边创建的线程也是daemon thread的
JVM在结束时需要等待user thread,但是不会等待daemon thread
JVM自身会创建一些daemon thread,比如GC
daemon thread的优先级更低
user thread可以被应用或线程自己关闭,JVM来终止daemon thread
不要再daemon thread里编写业务代码
设计篇
(1)Abstraction vs Encapsulation
Abstraction抽象:interface, abstract class
Encapsulation封裝:private, package-private, protected
(2)Overloading vs Overriding
Overload重载在编译期,Override重写在运行期
同一个类中overload方法,子类中override父类方法
可以overload静态方法,但不能override静态方法
private和final方法不能override,但可以overload
overload时需要修改方法的定义(参数表),override不需要
(3)Dependency Injection vs Factory Pattern
DI依赖注入需要第三方框架支持(比如Spring),工厂模式自己封装代码
DI松耦合设计,工厂模式耦合factory和object
DI框架替你常见管理实例,工厂通过getInstance()生产一个实例
DI更易于单体测试,更弹性灵活,但DI需要配置注入关系
(4)Singleton Pattern vs Static Class
单例提供的是Object,静态类提供的是方法
静态类性能更好
静态类方法不可override
静态类不便于测试
单例可以保持对象的状态等信息,静态类不可以
单例只在使用时加载(lazy load),静态类启动时加载
很多DI框架更容易支持单例
(5)Class vs Instance vs Object
Class的实例是对象。(An object is an instance of a class)
Class是用于创建对象的模板蓝图
Instance是类的一个唯一拷贝用于表现对象
Object拥有状态 state 和行为 behavior
JVM实际是先创建Instance后创建Object
具体参考这里
(6)Stack vs Heap
Heap存贮对象(JDK 7前String存在String Pool,之后也版本也存入Heap)
Stack存贮本地变量、方法定义、调用栈
所有线程共享Heap,各线程之间是不共享Stack的(本地变量是被线程隔离的)
创建thread后JVM会为其分配Stack
Heap的空间比Stack更大
可以指定Heap(-Xms-Xmx)和Stack(-Xss)的大小
Heap和Stack存储的数据结构是不一样的
其他
(1)trustStore vs keyStore
trustStore存储公钥和CA,keyStore存储私钥
trustStore验证证书,keyStore提供证书
创建SSLContext:trustStore-TrustManager(决定是否连接可信),keyStore-KeyManager(决定哪些连接在SSL握手时需要发到Server认证)
JRE默认trustStore保存在$JAVA_HOME/lib/security/cacerts
-Djavax.net.ssl.trustStore -Djavax.net.ssl.keyStore
-Djavax.net.ssl.trustStorePassword -Djavax.net.ssl.keyStorePassword
引用
证书标准 :X.509
编码格式 :
PEM-encoded certificate (domain.pem) Apache和*NIX服务器
DER-encoded certificate (domain.der) Java和Windows服务器
文件扩展名 :
keystore.jks - Java的Keytool工具生成的密钥库,存储非对称密钥对(私钥+x509公钥证书),有时也叫xxxx.keystore
keytool -genkey -alias localhostkey -keystore localhost.keystore -storepass password -keypass password
domain.key - 存放一个公钥或者私钥,并非X.509证书
openssl genrsa -des3 -out domain.key 2048
domain.csr - 证书签名请求,存放一个公钥,并非X.509证书,生成证书时要提交给证书颁发机构
openssl req -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr
domain.crt - Self-Signed Certificate *NIX系统
openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
domain.cer - 证书文件,只有公钥
domain.p12 - 证书文件,包含公钥及私钥,PKCS12(domain.pfx)
(2)Type 1, 2, 3, 4 JDBC Driver
Type 1:非Java实现,最早的驱动连接Access,需要把JDBC请求转化为ODBC后链接,又叫JDBC ODBC bridge driver(性能差)
Type 2:非Java实现,JDBC直接通过native API和DB链接,需要native library比如ocijdbc11.dll
Type 3:Java Net实现,通过代理服务和DB链接,client-server-database,又叫Net protocol JDBC driver
Type 4:纯Java实现,通过native protocol直接和DB链接,驱动JAR文件中包含所有数据库的调用,又叫thin JDBC driver
(3)32-bit vs 64-bit
32位CPU寻址范围是2的32次方,大概4GB的RAM(留给应用的大概Linux:2GB,Windows:1.5GB)
64位系统各OS寻址范围不同Windows可达8TB
32位OS只能按照32位Java,64位OS可以安装32位Java或64位Java
64位需要heap的大小多于32位的30-50%(object headers、object references)
64位GC中断时间更长
.class不依赖于多少位的Java编译器(互通编译,互通使用)
整型值的上限和多少位没关系Integer.MAX_VAlUE = 2^31 - 1
(4)PATH vs CLASSPATH
- JAVA_HOME:
指向JDK安装目录,比如C:\Program Files\Java\jdk1.8.0_65
Java本身不使用,第三方应用比如Tomcat使用,因为运行需要JDK支持
- JRE_HOME:
指向JRE安装目录,比如C:\Program Files\Java\jdk1.8.0_65\jre
Java本身不使用,第三方应用比如Tomcat使用,因为运行需要JDK支持,Tomcat优先使用JRE_HOME
JDK安装后有两套相同的JRE:C:\Program Files\Java\jdk1.8.0_65\jre(供JDK附属工具用的)、C:\Program Files\Java\jre1.8.0_65
***javac XXX.java 等价于 java -cp "%JAVA_HOME%\lib\tools.jar" com.sun.tools.javac.Main XXX.java
***Tomcat早期版本需要JDK把jsp编译成servlet,现在已经内置Eclipse的ECJ来支持JSP。
- CLASSPATH:
JVM类加载器查找class的路径
Java6后支持通配符不用挨个指定jar,CLASSPATH="C:\Program Files\Java\jdk1.8.0_65\lib"
也可以通过-cp 或 -classpath参数指定后供javac和java命令使用
目前来说基本无需设置:JDK工具能自己查找到这些jar;IDE会为project设置不同classpath
***Eclipse有自己的编译器ECJ来编译代码不需要javac。
- PATH:
操作系统的默认环境变量,去查找javac和java等工具的位置
-rt.jar、dt.jar、tools.jar
rt.jar: JRE提供的所有类java.lang.String、java.util.ArrayList等,在$JAVA_HOME/jre/lib下。源代码:$JAVA_HOME/src.zip
dt.jar: 不要包含Swing的BeanInfo文件,在$JAVA_HOME/lib下。
tools.jar: JDK需要的工具集,javac、javadoc等需要调用这个jar,在$JAVA_HOME/lib下。
***这些文件都是提供给JVM使用的,一般不需要特别设置。而且这三个文件在JDK9会被删掉分到不同的文件!
发表评论
-
Web API分页
2018-11-13 13:38 1571(一)分页类型 逻辑分页(客户端分页):从数据库将所有记录查询 ... -
JAXB实例入门
2017-06-09 10:17 1786JAXB(Java Architecture for XML ... -
Java Web项目中的Event
2017-06-05 09:42 1683(1)Servlet的事件和监听器 *** Servle ... -
关于Java SPI
2017-05-04 12:07 2044SPI:Service Provider Interface ... -
Jackson实例入门
2017-05-03 12:55 1716Jackson:Java平台的JSON解析器。 版本: ja ... -
为什么https被redirect成了http?
2016-11-14 09:35 7867全站HTTPS并不是配置证书CA,改改路径URL那么简单! ... -
简化Java代码
2016-10-09 11:25 1313样板代码Boilerplate Code的 ... -
Java Web Project based on Spring
2016-09-28 11:21 1038基于Spring开发Web项目的标配Library。 工具 ... -
Eclipse Scrapbook快速测试Java代码
2016-09-09 15:12 1331Scrapbook是Eclipse提供的特 ... -
Java爬取 百度图片&Google图片&Bing图片
2016-08-04 09:54 7624先看看抓取的结果。 抓关键字“美女”的百度图片: 抓关键字 ... -
20年Java发展历程(1995-2015)
2015-03-25 21:58 2391Java语言作为现在最流行的编程语言之一,它已经经历了整整20 ... -
Java命令行选项解析之Commons-CLI & Args4J & JCommander
2014-11-27 12:09 22557熟悉Linux命令的都知道几乎所有程序都会提供一些命令行选项。 ... -
Java调用Native API之JNA
2014-11-10 12:09 7824Java调用C/C++的Native API一般采用JNI(J ... -
Java执行SSH/SCP之JSch
2014-08-27 17:17 11580JSch (Java Secure Channel)是纯Jav ... -
GC日志分析
2014-07-18 08:54 2872GC:Garbage Collection 垃圾回收 (1) ... -
Java元组类型之javatuples
2014-05-20 10:58 27069关于方法的返回值,经常需要返回2个值或多个值的一个序列,比如数 ... -
Java 8 之 反编译Lambda表达式(CFR)
2014-04-14 09:34 6584CFR(Class File Reader) - anoth ... -
Java 8 之 Optional类
2014-04-08 14:38 2984在Java中,null代表一个不存在的对象,如果对它进行操作就 ... -
Java 8 之 Lambda表达式
2014-04-01 09:14 16201Java 8历时2年8个月,这次升级是继Java 5之后对Ja ... -
Java交互模式执行代码 之 Java REPL
2014-03-27 14:58 3323REPL(Read-Eval-Print-Loop)即“读取- ...
相关推荐
Java初学者在学习过程中往往会对某些概念和语法产生混淆,这些问题看似简单,实则深入理解后能大大提高编程效率和代码质量。以下几点是初学者容易混淆的问题,详细解析如下: ### 1. String与StringBuffer的区别 #...
以下是根据提供的文件信息,深入解析Java初学者容易混淆的知识点: ### 1. main()方法的语法格式 `public static void main(String[] args)`是Java应用程序的入口点。这里的`public`表示方法可被任何类访问,`...
文章通过一休编写的HelloWorld程序,指出很多初学者容易混淆的点,比如main方法的大小写、方法签名、参数名等。通过实际操作和观察编译器的错误信息,学习者可以更加直观地理解Java程序的运行原理。 2. **理解...
这个章节可能涵盖了Java中一些容易混淆的概念,比如值传递与引用传递、静态与非静态、接口与抽象类的区别等,有助于深化对Java语言的理解。 通过这份笔记的学习,读者将能系统地掌握Java的核心知识,并具备解决...
java学习者常常弄混淆的几个概念
相比于其他语言如C++,Java在语法结构上更为简洁明了,减少了复杂的概念和容易混淆的部分。例如,Java中去除了指针这一概念,避免了许多潜在的内存管理问题。此外,Java的语法与C++有很高的相似度,对于有一定C++...
Java 中的一些概念容易混淆,例如: * Java:是一种编程语言 * JDK:是 Java 开发工具包,包括 Java 编译器、Java 运行器等工具 * JRE:是 Java 运行环境,包括 Java 虚拟机、类加载器等组件 简单的 Java 程序 ...
1. **简单性**:Java的设计者们将C++语言中许多不易理解和容易混淆的部分去除,使得Java更容易理解与掌握。 2. **面向对象**:Java几乎一切都是对象。面向对象的思想贯穿了整个Java语言设计的核心。 3. **分布式**:...
1. **基本概念理解**:Java是一种面向对象的语言,但很多初学者会混淆面向过程和面向对象的区别。理解类、对象、继承、封装和多态等核心概念是基础,忽视这些可能导致编程思维的混乱。 2. **数据类型与内存管理**:...
本文将深入探讨这些容易混淆的概念,帮助初学者快速理解和掌握C#。 首先,我们要了解C#的总体框架。在C#程序中,`using`语句用于引入命名空间,使得我们可以直接使用该命名空间内的类型和方法,例如`using System;`...
在Java的学习过程中,经常会遇到一些容易混淆的概念,例如方法重载(overload)与方法重写(override),以及如何正确使用`super`关键字等。下面将对这些概念进行详细的解析,帮助大家更好地理解并掌握。 #### 方法...
在《Java程序设计》中,类的多态、方法的重载与重写就是这样一个关键且容易混淆的知识点。通过设计以“如何区别重载与重写”为主题的微课,可以有效帮助学生解决学习中的难题,同时巩固之前学习的知识点,并为进一步...
并发与并行是两个容易混淆的概念。并发指的是多个任务在同一时间间隔内开始执行,但它们的执行顺序和完成时间是不确定的,通常由操作系统的调度策略决定。而并行则强调的是多个任务同时执行,即它们的指令流是在不同...
虽然这两种声明方式在Java中都是合法的,但从习惯上来说,推荐使用第一种方式来声明数组,因为它更直观且不易引起混淆。 ##### 2. 数组的创建 数组的创建有三种主要的方式: - **创建并初始化数组**:可以在声明...
在IT行业中,尤其是在Java开发领域,反编译工具与混淆技术是两个重要的概念,它们分别涉及到软件的安全性和保护。本文将深入探讨这两个主题,并提供相关的知识点。 首先,我们来了解什么是反编译工具。反编译工具是...
本篇文章将深入探讨在Java学习过程中的一些关键知识点和容易混淆的概念。 基础篇: 1. JDK常用的包:Java Development Kit (JDK) 包含了Java运行环境和开发工具,其中核心的几个包如`java.lang`, `java.util`, `...
在 Java 编程过程中,“==”和equals方法是最容易混淆的概念之一。它们都可以用来判断两个对象是否相等,但是它们的使用场景和含义有着本质的区别。 **1.1 “==”运算符** - **基本类型**: 当我们使用“==”来比较...
这份高清版、文字版的资料很可能包含了深入浅出的解释和实例分析,以中文的形式呈现,使得国内开发者更容易理解和学习。 首先,Java中的易混淆知识点可能包括: 1. **静态与非静态成员**:静态成员属于类,而非...
JVM规范的发布,特别是有了中文译本之后,使得中文圈的程序员能够更容易地深入学习和研究Java虚拟机,不必受限于英语水平。 ### 翻译工作与技术背景 《Java虚拟机规范(JavaSE7版)》的中文翻译是由周志明(***)...