jdk>jre>jvm
jdk是java开发工具包,包含jre和编译器javac工具
jre是Java的运行环境,包含jav和类库和java命令
jvm是java虚拟机
.java源文件编译成十六进制的用于jvm运行的.class文件为java字节码文件
数据类型有:int(4字节),short(2字节),long(8字节),byte(1字节),char(2字节),float(4字节),double(8字节),boolean
基本类型 | 位数 | 字节 | 默认值 |
---|---|---|---|
int | 32 | 4 | 0 |
short | 16 | 2 | 0 |
long | 64 | 8 | 0L |
byte | 8 | 1 | 0 |
char | 16 | 2 | ‘u0000‘ |
float | 32 | 4 | 0f |
double | 64 | 8 | 0d |
boolean | 1 | false |
私有性:public<protected<default(不写)<private
final:
finally:异常处理中的try/catch/finally,finally代表最终一定执行,一般用于施放资源
finalize:object下的方法,在垃圾回收GC时,这个对象被回收时使用该方法
为特定域分配单一存储空间,使用static可以不用重复new创建类的对象,直接进行调用
不能,static方法是编译时静态绑定的,方法覆盖是基于运行时动态绑定的
不能,static在java虚拟机载入时初始化,而此时非static变量和资源都还没有创建出来
可以,初始化加载静态资源,同级可以引用
基本上代码块分为三种:Static静态代码块、构造代码块、普通代码块
代码块执行顺序静态代码块——> 构造代码块 ——> 构造函数——> 普通代码块
继承中代码块执行顺序:父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器
面向过程:
面向对象:
封装:将具体的事务抽象的封装成类
继承:子类继承父类,具有父类的属性和方法,通过继承可以不改变原来类的情况下进行拓展
多态:子类继承父类后,子类的属性和方法可以具有不同的数据类型和表现出不同的行为
三个条件:继承,重写,向上转型
重载:方法名相同,参数不同,发生在同一个类里面
重写:方法名和参数都相同,发生在父类和子类之间
重载无法根据返回值来进行区分,仅仅返回值不同的重载不被允许
构造器不可以被重写,但是可以重载,子类的构造器要调用父类的构造器
抽象类中:可以有具体的实现,各种变量,可以有静态方法和静态代码块,只能继承一个抽象类
接口:只能由抽象方法组成,只能有static final 变量,没有静态方法和静态代码块,可以实现多个接口
不可以,final禁止继承,抽象类又要被继承,矛盾
创建的对象不可改变,修改会创建一个新的对象,如String,Integer
好处:线程安全
可以,不可变的数组中存入可变的对象引用,final A a[ ]= new a[ ]{ }
值传递:只传递值
引用传递:传递引用,也就是传递引用的地址
java只有值传递:java的引用传递,传递的是引用地址的值
==用于
equals用于
用于获取哈希码(也叫散列码),返回一个int值。
值为该对象在哈希列表中的位置,键值对形式存储,通过哈希码找到对象的时空复杂度为1
HashSet如何检查重复来说明:
判断时,先根据hashCode判断再进行equals判断,如果重写equals方法改变判断,而hashCode不重写,会导致hashCode不一致但是用equals判断为true的情况
String:不可变,线程安全,改变创建新的对象
StringBuffer:可变,线程安全,有同步锁,改变修改原来的对象
StringBuilder:可变,非线程安全,
1.7从方法区移到堆中,1.8还是在堆中
jvm为了提升性能和减少内存开销,避免字符的重复创建,其维护了一块特殊的内存空间,即字符串池,当需要使用字符
串时,先去字符串池中查看该字符串是否已经存在,如果存在,则可以直接使用,如果不存在,初始化,并将该字符串放
入字符串常量池中。
便于实现字符串池(String pool)
如果每一个String对象都去创建一个新的String对象,十分浪费空间,所以,在堆中,有字符串池来记录String,初始化一个String变量时,字符串池中有这个字符串,就将返回字符串池中的引用,避免重复创建一样的字符串对象
线程安全(读写问题)
字符串不可变,不能写,不会出现竞争问题
避免安全问题(外部攻击)
网络和数据库连接中多为字符串形式,不可变可以保证安全性
加快字符串处理速度
保证了hashCode的唯一性,在键值对中,可以直接缓存,不用重新计算,处理速度块
字符型常量:
字符char的常量,单引号引起的一个字符,相当于一个整型值( ASCII 值),可以参加表达式运算,只占2个字节
字符串常量:
字符串String的常量,双引号引起的若干个字符,代表一个地址值(该字符串在内存中存放位置,相当于对象)
new String(“aaa”)创建了两个字符串对象,一个在堆内存中,一个在字符串常量中
不是,基本类型:short,int,long,char,boolean,float,double和byte
不变:改变实质为创建新的对象
常量池优化:String对象创建后,会在字符串常量池缓存,下次创建相同的对象,返回池中的引用
final:String用final定义,String类无法继承,系统安全
String不可变,HashCode唯一,做key时不用重新计算,相对于其他对象更块
java为每一个基本类型设置了包装类型:
原始类型: boolean,char,byte,short,int,long,float,double
包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
区别:
基本类型不可以为null,而包装类型可以
基本类型不可以适配泛型,而包装类型可以
基本类型比包装类型更加高效
自动装箱:自动将基本类型转化为包装类型
声明的包装类型可以用基本类型的方式实例化,不用手动转化类型
Integer num = 9;
自动拆箱:自动将包装类型转化为基本类型
包装类型可以直接以基本类型的方式进行使用,不需要手动转化
num++;
Integer是int的包装类,int是基本类型
Integer需要实例化才可以使用,int不需要
Integer实质是对象引用,指向new出的Integer对象,int直接存储数值
Integer默认值为null,int默认值为0
实质上为两个对象的引用对比,使用==,结果为false
使用==,由于自动拆箱机制,会转变为基本类型进行对比,结果为true
非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。
(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
Integer b = new Integer(10000);//声明对象--指向堆中对象
Integer c=10000;//自动装箱--指向java常量池
System.out.println(b == c); // false
对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
在运行状态下,动态的加载类的属性和方法的机制叫做反射机制
优点:灵活,运行时获取
缺点:性能较低,需要解析字节码
1.Class c=User.Class;或者Class c=Class.forName("相对路径");等获得Class
2.User u=(User)c.newInstance();无参创建对象或者c.getConstructor(String.class).newInstance("构造参数")创建对象
3.Method m=c.getMethod();或者Field f=c.getField();等获取属性或者方法
4.通过m.invoke(c,"方法参数")或者f.set(c,"值")。如果是私有,需要f.setAccessible(true);关闭程序安全,再操作私有属性
jdbc
通过反射加载jdbc的包
spring框架
xml配置bean:
类型参数化,在编译时才确定具体的参数类型,可以用在类,接口,方法中
jdk1.4. 没有泛型时,使用Object时
例子:
//存入两个不同类型的数据到List中
List list = new ArrayList();
list.add("www.cnblogs.com");
list.add(23);
//取出时进行强制类型转换
String name = (String)list.get(0);
String number = (String)list.get(1); //ClassCastException
使用泛型类型的好处有:
泛型原理:
泛型语法是一种语法糖,它的原理就是类型擦除,泛型只存在于编译阶段,不存在执行阶段,编译之后的class文件没有泛型。
(语法糖指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。)
类型擦除:使用泛型的时候加上类型参数,编译器在编译的时候去掉类型参数。
如:
//<T> 泛型参数
public class Caculate<T> {
private T num;
}
大部分情况下,编译器会将T编译为Object类型,替换掉泛型
//擦除结果
public class Caculate{
public Caculate(){}
private Object num;
}
使用到了extends和super语法的有界类型,将不是直接以Object类型进行擦除,使用指定的类型进行擦除
限定通配符:extends和super:用于限定?
? extends T: 指定为改类子类
? super T:指定为改类父类
非限定通配符:?:表示类型为任何类型,未知的类型
<String>
传递给一个接受List<Object>
参数的方法吗?不可以,Object范围比String大,会导致编译错误
不可以。因为 List 可以提供编译期的类型安全保证,而 Array 却不能。
ArrayList<String>
与ArrayList<Integer>
是否相等?相等。两者Class一致。
在类编译的时候,才体现出两者的差别,此时会进行泛型检查
序列化:将java对象转化为字节序列的过程,以便在网络上进行传输。对象保存在JVM中,当JVM停止工作时,将对象序列化为二进制流,保存在文件中,当再次需要时,读取二进制文件反序列化获得对象。
反序列化:将字节序列转化为java对象的过程,客户端从文件中或网络上获得序列化后的对象字节流,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。
原因:需要对对象进行持久化和网络传输
详细原因:
对象序列化可以实现分布式对象
主要应用例如:RMI(即远程调用Remote Method Invocation)要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样
java对象序列化不仅保留一个对象的数据,还递归保留对象引用的每个对象的数据
保存整个对象层次,进行深度复制
序列化可以将内存中的对象写入到文件或者数据库中
对象,数据,文件保存格式不统一,通过序列化为二进制,方便保存
实现Serializable接口或者Externalizable接口。
实现Serializable接口:原始接口,继承即可,不用实现方法
实现Externalizable接口:Externalizable
继承自Serializable
,该接口中定义了两个抽象方法:writeExternal()
与
readExternal()
,两个抽象需要重写,否则对象变量为默认值
实现Serializable接口 | 实现Externalizable接口 |
---|---|
系统自动存储必要的信息 | 程序员决定存储哪些信息 |
Java内建支持,易于实现,只需要实现该接口即可,无需任何代码支持 | 必须实现接口内的两个方法 |
性能略差 | 性能略好 |
serialVersionUID用来验证对象版本一致性的。反序列化时,会讲serialVersionUID与本地相应类的serialVersionUID进行比较,不一致则报版本不一致异常。
如果不指定serialVersionUID的值,在序列化和反序列化时,JVM都会自动生成一个serialVersionUID,进行持久化或者网络传输时,反序列化的serialVersionUID会与序列化时的serialVersionUID不同而导致异常。
指定serialVersionUID可以使该对象的序列化和反序列化的serialVersionUID保持一致。
不修改,除非出现版本异常
使用transient关键字修饰变量(不可以修饰类和方法),可以使一些字段(变量)避免序列化,值为初始值
不会,静态变量优于对象存在,随着类的加载而加载,而序列化是针对对象的
Java 中,所有的异常都有一个共同的祖先 java.lang
包中的 Throwable
类。Throwable
类有两个重要的子类 Exception
(异常)和 Error
(错误)。
Exception
和 Error
二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Exception
:程序本身可以处理的异常,可以通过 catch
来进行捕获,通常遇到这种错误,应对其进行处理,使应用程序可以继续正常运行。
Exception
又可以分为运行时异常(RuntimeException, 又叫非受检查异常)和非运行时异常(又叫受检查异常) 。
Error
:Error
属于程序无法处理的错误 ,我们没办法通过 catch
来进行捕获 。例如,系统崩溃,内存不足,堆栈溢出等,编译器不会对这类错误进行检测,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序本身无法恢复。
运作时异常包括(非受检查异):RuntimeException及其子类:表示运行期间会出现的异常
NullPointException(空指针)
、NumberFormatException(字符串转换为数字)
、IndexOutOfBoundsException(数组越界)
、ClassCastException(类转换异常)
、ArrayStoreException(数据存储异常,操作数组时类型不一致)
等。一般异常(受检查异常):包含IO 异常、ClassNotFoundException
、SQLException
等
throw :在方法内部使用,只能抛出一个异常
throws:在方法声明上使用,可以抛出多个异常
NoClassDefFoundError :Error类型的异常,JVM 或 ClassLoader 尝试加载某类时在内存中找不到该类的定义,该动作发
生在运行期间,即编译时该类存在,但是在运行时却找不到了,可能是编译后被删除了等原因导致。
ClassNotFoundException :使用 Class.forName, ClassLoader.loadClass 或 ClassLoader.findSystemClass 动态加载类到内
存的时候,通过传入的类路径参数没有找到该类,就会抛出该异常;另一种抛出该异常的可能原因是某个类已经由一个类
加载器加载至内存中,另一个加载器又尝试去加载它
Error:
Exception:
受检查异常:一般异常
不受检查异常:运行时异常
catch可以省略,try处理运行时异常,try+catch处理运行时和一般异常,finally进行收尾
会执行,finally在return之前执行
当一个方法发生异常,方法创建一个异常对象转交给jvm,异常对象包含异常的各种信息,这个过程叫:抛出异常
在抛出异常的过程中,可能有一系列的调用,这时有一个调用栈,jvm查看调用栈,找到抛出的处理异常的方法进行处理,没找到,则默认打印异常信息并终止程序。
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。
使用了适配器模式和装饰器模式
适配器模式:
Reader reader = new INputStreamReader(inputStream);
从字节流对象中获取字符流的对象。
把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作
原文:https://www.cnblogs.com/theworld-timestop/p/15169217.html