基本数据类型和运算符
- byte
- short
- int
- int[]
- long
- boolean
- char
- char[]
- float
- double
- !
- %
- &&
- ||
- +
- //
- ++
- - -
注意点
数据类型 | 封装类 | 特点 |
---|---|---|
int | Integer | int初始化是0,Integer初始化是null。Integer是int的封装类,可以实现和字符串的转换 |
char | Character | char初始化是_,Character初始化是null |
long | Long | long初始化是0,Long初始化是null |
byte | Byte | byte初始化是0,Byte初始化是null |
short | Short | short初始化是0,Short初始化是null |
float | Float | float初始化是0.0,Float初始化是null |
double | Double | double初始化是0.0,Double初始化是null |
boolean | Boolean | boolean初始化是false,Boolean初始化是null |
PS:泛型定义时也不支持数据类型,只能是类
如
List<int>
就不行,但是List<Integer>
可以
装箱和拆箱
在自动装箱的时候,Java虚拟机会自动调用Integer的valueOf方法;
在自动拆箱的时候,Java虚拟机会自动调用Integer的intValue方法。
Byte、Short、Integer、Long、Char这几个装箱类的valueOf()方法是以128位分界线做了缓存的,假如是[-128,127]区间的值是会取缓存里面的引用的,以Integer为例,其valueOf(int i)的源代码为:
1 | static final int low = -128; |
Integer 在静态代码块中缓存了-128 ~ 127 之间的数字(IntegerCache),范围外的就只能去new了,所以integer在比较这个区间内的地址是相同的
参考路径
http://www.jianshu.com/p/946b3c4a5db6
判断,筛选和循环
- if
1 | public int say(int word){ |
- switch
1 | switch(a){ |
- for
1 | for(int i = 0;i<10;i++){ |
- while
1 | public void speak(int key){ |
- foreach
1 | int[] bbs = {1,2,3,4,5}; |
- do while
1 | int a = 10; |
- 5 > 4 ? “y” : “n” 返回的是y
面向对象
- 思想
- 万事万物都是对象
- 每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法)
- 比如我们考虑一只狗,那么它的 状态是:名称,品种,颜色 行为:吠叫,摇摆,跑等
1 | public class Dog{ |
构造方法
- 介绍
- 构造方法是一种特殊的方法
- 构造方法的方法名必须与类名相同
- 构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型
- 构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域
1 | public class Puppy{ |
值引用
java中方法参数传递方式是按值传递。
如果参数是基本类型,传递的是基本类型的字面量值的拷贝。
如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。
参考路径
Clone
clone是对对象进行复制,是一维层面的深拷贝,会产生一个新对象,但是对象里的引用还是指向同一个,方法是native方法,效率高。
注意点
- clone的对象必须要实现Cloneable接口,不然CloneNotSupportedException异常,clone实现的是浅拷贝,如果要深拷贝,需要重写方法,注意重写后的方法的返回值可以是Object的子类
- 数组的clone,复制的仅仅是数组中的元素,比如数组中元素为引用类型,那仅仅复制引用。若clone的对象中含有链表,则应单独对链表进行循环复制
arraycopy
System.arraycopy是复制一个数组,也是native方法
二维数组或对象数组
arraycopy 也只能实现浅拷贝,因为java没有二维数组的概念,他是数组的数组,所以arraycopy 拷贝二维数组只能是拷贝引用,arraycopy拷贝对象数组也是只能拷贝引用。arraycopy只要拷贝一维数组的基础类型时才是深拷贝
HashCode
hashcode和equal的区别
hashcode能大概区分是否是同一对象,equal是能准确区别对象
hashcode不同,则两个对象不同
hashcode相同,则对象不一定相同,需要进一步equal比较
注意点
- 设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()方法就会生成一个不同的散列码
- 重写equal方法后,一定也要重写hashcode,否则不能使用hashmap了
分装类实现
我会基本列举下面封装类的所有构造方法
在String类中的hashCode是根据String类中包含的字符串获取的,根据哈希算法获取到一个哈希码,那么只要我的字符内容是相等的,我的哈希码也是相同的。
new String(“”)和直接赋值的区别,在于new String(“”)创建两个String对象,直接赋值创建一个
更多区别参考:String和New String()的区别、String s=new String()与String s = “”的区别
1 | public static void main(String[] args) { |
Integer类中的hashCode和String是一样的,也是根据类中包含的值去生成的哈希码。两个相同大小的integer值,那么它的hashCode也是相等的。这里不用考虑127这个分界线
1 | public static void main(String[] args) { |
Character类也是一样的
1 | public static void main(String[] args) { |
Object类中的hashCode则和之前的不一样了,他是根据对象的内存地址经过哈希算法之后获取到的哈希码,由于每个对象的内存地址不相同,所以hashCode是不同的。
toString
是指把对象转成字符串的方法。
- 当使用+的时候
- 用println方法的时候
注意
不要在toString方法中用‘+this’这种操作,这样会不断调用toString方法,导致死循环
速学路径
http://www.voidcn.com/blog/u012413167/article/p-5978865.html
继承
- 介绍
- 继承一个类,子类会获得父类的所有成员变量和成员方法
- 一个类只能继承一个父类,但是可以被多个子类继承
1 | public class Animal { |
1 | public class Dog extends Animal { |
1 | public class Test{ |
1 | 结果: //animal变量访问变量是看 声明的类型,访问方法是看 实例的方法! |
- instanceof 运算符
- 左面的对象是右面的类创建的对象时,该运算符运算的结果是true,否则是false
- instanceof左边操作元显式声明的类型与右边操作元必须是同种类或右边是左边父类的继承关系
1 | public class Test{ |
1 | 结果: |
- 重写
- 在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
向上转型&向下转型
向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口
向下转型:父类引用的对象转换为子类类型称为向下转型。
前者是一个向上转型,Animal dog 引用指向new Dog();子类对象当成父类对象,只能调用父类的成员,如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法(这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。
在向下转型过程中,分为两种情况:
- 如果父类引用的对象如果引用的是指向的子类对象,那么在向下转型的过程中是安全的。也就是编译是不会出错误的。
- 如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。
修饰词
类型 | 同类 | 同包 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
private | yes | |||
default | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
- private
- 除了class自己之外,任何人都不可以直接使用
- default
- 类可以访问在同一个包中的其他类(朋友)的成员
- protected
- 只有相同的包下的类(朋友)和自己的子类(子女)才能访问
- public
- 该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
- final
- final类不能被继承,没有子类,final类中的方法默认是final的
- final方法不能被子类的方法覆盖,但可以被继承。
- final成员变量或参数表示常量,只能被赋值一次,赋值后值不再改变。
- final不能用于修饰构造方法。
- static
- static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块
- 被static修饰的成员变量和成员方法独立于该类的任何对象,即不需要实例化对象就能用类名.变量(方法)来使用
1 | private static final String StaticFinalVar = "aaa"; |
- this
- this是对象,this.成员变量,this.函数(哪个对象调用的,this就代表该对象)
- 函数的参数与成员变量重名时,赋值语句使用 this.name = name;
- this(name); 根据this所带的参数判断调用哪个构造函数。
- super
- super(); 调用父类构造函数
- super.成员函数; 调用父类成员函数或变量
1 | public class test{ |
1 | public class exam extends test{ |
1 | 运行结果: |
静态代码块
- static
- 静态代码块里的使用的变量和方法也必须是static的
- 静态代码块是在类加载时自动执行的,非静态代码块是在创建对象时自动执行的代码,不创建对象就不会执行该类的非静态代码块
- 执行顺序:静态代码块——非静态代码块—-构造函数
1 | public class StaticBlock { |
1 | 运行结果: |
1 | public class HelloA { |
- 原理
- 实例化有两个步骤:1、类加载 2、new 对象
- 一个类在第一次被使用的时候会被类加载,然后在整个应用程序的生命周期当中不会再次被加载了,就加载这一次
- 因为static{}是在类加载时候被加载的,所以static{}也只会被加载一次
- 内部类与静态内部类的区别
- 静态内部类相对与外部类是独立存在的,静态内部类中无法直接访问外部类中变量、方法。如果要访问的话,必须要new一个外部类的对象,使用new出来的对象来访问。但是可以直接访问静态的变量、调用静态的方法
- 普通内部类作为外部类一个成员而存在,在普通内部类中可以直接访问外部类属性,调用外部类的方法
- 如果外部类要访问内部类的属性或者调用内部类的方法,必须要创建一个内部类的对象,使用该对象访问属性或者调用方法
- 如果其他的类要访问普通内部类的属性或者调用普通内部类的方法,必须要在外部类中创建一个普通内部类的对象作为一个属性,外同类可以通过该属性调用普通内部类的方法或者访问普通内部类的属性
匿名内部类
匿名内部类不能访问外部类方法中的局部变量,除非变量被声明为final类型
- 这里所说的“匿名内部类”主要是指在其外部类的成员方法内定义,同时完成实例化的类,若其访问该成员方法中的局部变量,局部变量必须要被final修饰。
- 原因是编译程序实现上的困难:内部类对象的生命周期会超过局部变量的生命周期。局部变量的生命周期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,退栈,这些局部变量全部死亡。而内部类对象生命周期与其它类一样:自创建一个匿名内部类对象,系统为该对象分配内存,直到没有引用变量指向分配给该对象的内存,它才会死亡(被JVM垃圾回收)。所以完全可能出现的一种情况是:成员方法已调用结束,局部变量已死亡,但匿名内部类的对象仍然活着。
- 如果匿名内部类的对象访问了同一个方法中的局部变量,就要求只要匿名内部类对象还活着,那么栈中的那些它要所访问的局部变量就不能“死亡”。
- 解决方法:匿名内部类对象可以访问同一个方法中被定义为final类型的局部变量。定义为final后,编译程序的实现方法:对于匿名内部类对象要访问的所有final类型局部变量,都拷贝成为该对象中的一个数据成员。这样,即使栈中局部变量已死亡,但被定义为final类型的局部变量的值永远不变,因而匿名内部类对象在局部变量死亡后,照样可以访问final类型的局部变量,因为它自己拷贝了一份,且与原局部变量的值始终一致。
- 最后,Java 8更加智能:如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰。此外,Java 8的λ表达式也与此类似只能访问final外部变量但不要求用final修饰,不过,变量同样不能被重新赋值。
集合
- Collection (接口)
- List (接口)
- ArrayList (实现类)
- 非线程安全
- Vector (实现类)
- 线程安全
- ArrayList (实现类)
1 | List<Object> objectList = new ArrayList<Object>(); |
- Set (接口)
- HashSet (实现类)
- 不能有重复的元素
- HashSet (实现类)
1 | Collection books = new HashSet(); |
- Iterator (接口)
- 只能用于Collection的遍历
1 | Iterator it = books.iterator(); |
排序函数
- 实现Comparable接口
- 重载比较函数
1 | /** |
- Map (接口)
- HashMap (实现类)
1 | Map map = new HashMap(); |
- 遍历Map
1 | public class Test{ |
接口和抽象类
- interface
- 接口是抽象方法的集合。一个类实现一个接口,从而继承接口的抽象方法
- 不能实例化一个接口
- 接口不包含任何构造函数
- 所有在接口中的方法都是抽象的
- 一个接口可以扩展多个接口
- 在接口中的每个方法也隐式抽象的,所以abstract关键字不需要
- 在接口中的方法是隐式公开的,即默认是public,不能写成private
1 | //电脑类 |
1 | //USB接口 |
1 | //MP3实现了USB接口的方法 |
1 | //测试 |
- abstract
- 如果我们要定义的一个类的时候,没有足够的信息来描述一个具体的对象,还需要其他的具体类来支持
- 这个时候我们可以考虑使用抽象类。在类定义的前面增加abstract关键字,就表明一个类是抽象类。
- 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
- 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
1 | //形状父类 |
1 | public class Circle extends Shapes { |
- 区别
- 接口作用
- 在业务逻辑设计的时候,可以只关注逻辑,不去写具体实现。等到接口写完后,你完全可以把具体实现交给其他人做,其他人按照你的业务逻辑就能完成。
- 当知道一件事肯定要多次被做或者将来功能扩展的时候会被做,但是每次做的方法都不一样的时候,你可以写个接口,相当于声明了这个方法,而具体实现可以等用的时候再写,这样可以使代码更加简洁明了。
- 抽象类作用
- 多个类把共同的代码片段的抽取出来,做成一个基类。
- 相同行为,不同代码的成员方法,可以用抽象方法来代替,不去具体实现。
- 相同的代码,基类可以统一来具体实现了,节约了子类的代码
- 两者区别
- 接口更加零散,他专注于概括不同的方法。抽象类更加像一个基类,为不同的子类做一个总的基础。
- 抽象类是对类的抽象,而接口是对行为的抽象
- 接口作用
多态
多态是同一个行为具有多个不同表现形式或形态的能力
- 多态的思想
- 继承,接口实现
- 狗是动物,猫是动物,鱼是动物
- 吃可以是吃饭,吃零食,吃大餐
- 重载
- 被重载的方法必须改变参数列表(参数类型不同,或参数个数不同)
- 或是不同的返回类型,但方法名要一样
- 可以改变访问修饰符
- 运算符重载
- 运算符两边的东西不一样,作用也不一样
- 继承,接口实现
- 示例
- 例子太多,就不举啦😀
字符类
- String和char[]
1 | String str = "GG"; |
- String是一个引用类型,不是基本数据类型
- StringBuffer
- 线程安全的
- StringBuilder
- 线程非安全的,会造成死锁
- StringBuffer与StringBuilder
- StringBuilder > StringBuffer
- 他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了。
- 如果要操作少量的数据用 = String
- 如果单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
- 如果多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
- StringAPI
1 | char charAt(int index) //返回指定索引处的 char 值。 |
枚举类
- enum
1 | public enum Color { |
1 | public enum Signal { |
1 | public enum Color { |
1 | public class Main { |
1 | 结果: |
时间类
- Date
1 | public class Main { |
1 | 结果: |
- SimpleDateFormat
- 一个格式化的时间工具类
- String转Date
1 | public static void main(String[] args) { |
- Date转String
1 | public static void main(String[] args) { |
加密类
- Hash 算法
- 它的算法的特征是不可逆性,并且在计算的时候所有的数据都参与了运算,其中任何一个数据变化了都会导致计算出来的Hash值完全不同,所以通常用来校验数据是否正确或用作身份验证。
- MD5
- 最常用的哈希算法
1 | public String getMD5(String s) { |
- SHA
- SHA加密原理又叫安全哈希加密技术,是当今世界最先进的加密算法
- MD5和SHA的区别
- MD5比SHA快,SHA比MD5强度高,更安全
- salt 盐值
- 混淆原数据的值