本周开始了高级特性的学习,已经不能非常清晰的了解每一个知识点了,周末要好好总结下。
Advance Java Progarme
Model 1 高级特性
一. static修饰符
- 修饰变量(成员变量):
- 类变量:在类加载时即分配内存空间进行存储
- 能够被类的实例所共享
- 在某种意义上更类似于全局变量,可以在当前类中所有方法直接访问,外部类权限允许的范围内使用类名.变量名访问
- 访问方式:
- 类名.变量名
- 对象名.变量名
- 修饰方法:对静态变量复杂初始化
- 类方法:可以无实例调用
- static修饰的方法不能访问非static变量
- 非static方法不能被重写为非static方法
- 修饰代码块
- 只在类加载时执行一次
- 非static修饰的代码块依赖对象。所以在每次构建对象时都会执行一次
- 只在类加载时执行一次
二.静态导入(jdk5.0)
- 用来引入使用到的静态成员
- 语法:
import static packageName.className.staticMember;
#
三. final关键字(不能修改)
修饰变量:使用final修饰的变量是常量,在第一次初始化后不能修改,必须显式初始化
- 初始化成员变量:
- 类变量:
- 声明时直接初始化
- 静态代码块中初始化
- 实例变量:
- 声明时直接初始化
- 在构造器中显式初始化
- 实例代码块中初始化
- 类变量:
- 初始化局部变量:
- 声明时直接初始化
- 初始化成员变量:
修饰方法:不能被重写
修饰类:不能被继承 String Integer
四.访问修饰符
当前类 相同包 不同包子类 其他
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
- 所有的访问修饰符都可以用来修饰成员属性和成员方法,并且访问权限如上
- 所有的类(非内部类)只能使用public或者default packae修饰
五. 在整个应用范围之内,对于class Singleton只能有一个实例对象存在
六. abstract : 抽象
- 类:
- 抽象类是对类的抽象,存在的目的就是用来被继承,以提高代码的可重用性。
- 抽象类不能被实例化。
- 可以声明抽象类类型的变量:Animal an;且可以接受所有继承其类的实例。
- 抽象类可以像普通类一样具有所有的属性和行为。
- 抽象类也可以具有非抽象方法。
- 方法:
- 抽象方法没有方法体。
- 存在的目的就是为了被衍生类重写,以体现多态的特征。
- 抽象方法所在的类必须是抽象类。
- 如果衍生类继承了抽象类,并且抽象类中有抽象方法,那么衍生类必须实现抽象方法,或者衍生类也是一个抽象方法。
七. Interface : 接口
- 用来定义规则,标准。
- 接口是一种更纯粹的抽象类,类和方法全部为abstract方法,所有变量都为static final变量,修饰关键字可省略。
- 一个类可以实现多个接口。(解决部分java多继承带来的问题)
- 关键字 implements。
- 接口不能被实例化,可以声明接口类型的变量,存在目的就是为了被实现。
- 一个类实现接口,那么这个类必须实现这个接口所有的方法,或者类本身也是抽象类。
接口可以多继承。
- 接口和抽象类的对比
- 抽象类是对类的抽象类
- 接口是对抽象类的极致抽象
- 在实际应用中根据问题域不同选择不同的抽象类,如果只关注行为选择接口,更关注属性选抽象类。
- 接口和抽象类的对比
八. 内部类:
- 定义在比package更小范围内的类。换句话说就是定义在类内部,或者方法体内部,甚至比方法体更小范围的代码块中的类。内部类都可被外部类替换,但使用内部类可以减少命名冲突,提供更丰富的代码组织形式。
- 内部类:
- 静态内部类(嵌套内部类):可以脱离外部类的实例独立存在。
- 不和它所在的外部类同名。
- 只能访问范围内的静态变量和方法
- 在外部类的外部实例化静态内部类:
new StaticOuterClass.StaticInnerClass()
- 静态内部类只能访问外部类的静态成员,包括私用静态成员。
- 在外部类的内部构建内部类的实例:
new InnerClass()
- 成员内部类(实例内部类):依赖外部类的实例存在才能构建实例内部类。
- 可以访问外部类的所有成员
- 成员内部类中只能有final修饰的静态成员。
- 如果外部类定义有和内部类同名的实例变量,访问采用
Outer.this.InnerMember
- 在外部类的外部构建内部类的实例
new OuterClass().new InnerCalss()
- 在外部类的静态方法中创建实例使用
new OuterClass().new InnerCalss()
- 在外部类的实例方法中构建内部类的实例
new InnerClass()
- 局部内部类:
- 定义在方法体部,或者比方法体更小的代码块中。
- 类似于局部变量,不能声明为protected,public,static
- 可以访问所在方法体能够访问的所有外部类中的成员。jdk7.0局部内部类访问方法体中声明的变量时只能访问常量。
- 匿名内部类(没有名字的局部内部类)
- 没有类名的局部内部类。
- 没有class,extends,implenments。
- 没有构造器。
- 一般隐式的继承某一个父类或者某一个结构。
- 静态内部类(嵌套内部类):可以脱离外部类的实例独立存在。
九. Object
java中所有类都直接或者间接的继承自java.lang.object
- getClass():返回当前对象的运行时类
equals(Object obj):判断obj对象是否和当前对象相等。Object的equals方法和==等价,实现功能看情况需要重写。
- 对象相等(equals to)
对象同一(==)
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { //如果需要绝对相等可以用运行时类判断 String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
- hashCode():返回当前对象的hashCode值。
- toString():返回代表当前对象的字符串,默认打印是运行时类的名字@十六进制数。当打印一个引用变量的值时默认打印的就是toString方法的返回值。因为toString方法没有使用final修饰,所以可以被子类重写,如String。
十. String StringBuilder StringBuffer
- String为不可变字符序列,其余两个可变。
String str = "123";
- 常量表达式”a”+”bc”等价于”abc”
- StringBuilder:非线程安全 jdk1.5
- StringBuffer:线程安全 jdk1.0
- 如果需要频繁拼接字符串推荐使用StringBuilder和StringBuffer。
- intern():返回字符串的规范化表示(字符串常量),只要字符串对象维护的字符序列是一样的,那么调用intern方法的返回值用==比较,返回值为true。
- java.util.StringTokenizer;splite
十一. 包装类
- byte Byte -128~127
- short Short -128~127
- int Integer -128~127(唯一可修改最大缓存值)
- long Long -128~127
- float Float 不缓存
- double Double 不缓存
- char Character <=127
- boolean Boolean 提供两个常量
Integer in = new Integer("123");//装箱
int out = in.intValue();//拆箱
- jdk5.0后
Integer in2 = 200;//自动装箱使用valueOf()方法缓存
int out2 = in2;//自动拆箱使用typeValue()方法
基本数据类型和String类型值之间的转换
String Inteher
Integer.parseInt(String);
WrapClass.parseType(String);
model2 高级特征
一. 集合框架(Collection)
- 概念:是一个对象,用来存放其他对象,并且只能存放对象。
- 组成:
- 接口:接口规定了每一种类型的集合应该实现的方法。
- 实现:每一个类型的集合的具体类比如:ArrayList,HashTable。
- 算法:数据增加,修改和删除的实现。
- java.util;
二. 集合框架的大类
- java.util.Collection:存放单个值。
- Set:无序的,不允许存放重复值且最多允许一个null值,不提供通过index访问元素的操作。
- HashSet:底层维护一个HashMap实例,存储借助于HashTable实现。(根据对象的hashCode()方法的返回值进行hash()运算,然后使用运算得到的hash值和表长-1的值进行&运算得出在表中的存储位置,后添加在相应位置的链表头部)。
- note:
- HashSet在判断对象值是否重复时采用的规则是,先判断哈希值是否相同,如果相同,再调用equals方法进行比较,如果equals返回结果为真,那么不执行插入动作。所以对于自定义的对象,如果要在hashSet集合中存储,需要重写hashCode()和equals()方法。对于hashCode()的重写,需要尽可能的保证当equals()返回值为false,hashCode()返回值尽可能散列,以提高hashSet插入数据时的插入效率。
- SortedSet:有序的,不允许重复值的集合。存放在SortedSet集合中的所有数据要求必须拥有自然排序规则(implments Comparable 自然排序)或者在创建SortedSet集合对象时指定一个Comparator()(客户化排序)方法。所有存放在SortedSet中的数据不能ClassCastException。所以要保证数据类型相同。
- TreeSet:所有数据要求必须拥有自然排序规则(implments Comparable{CompareTo(Object obj)})或者在创建SortedSet集合对象时指定一个Comparator(obj1,obj2)方法。return值为-1,0,1,0代表重复,正数代表大(this>obj,obj1>obj2)。
- HashSet:底层维护一个HashMap实例,存储借助于HashTable实现。(根据对象的hashCode()方法的返回值进行hash()运算,然后使用运算得到的hash值和表长-1的值进行&运算得出在表中的存储位置,后添加在相应位置的链表头部)。
- List:有序的线性结构。有序的集合,这个接口下的所有集合都允许用户精确的控制元素在集合中的存储位置。并且通过他们的integer index来访问,允许存放重复值。
- ArrayList:借助于数组实现,允许存放空值。(Vector是线程安全的ArrayList)
- 数组的长度不能修改,所以通过方法来判断是否扩容数组。
- 存储空间连续,随机访问效率较高。
- 如果操作数据的插入删除,涉及内存数据搬移,操作效率较慢。
- LinkedList:借助于双向链表实现的有序的,允许重复值和null的集合。
- 链表维护的所有数据是离散的分布在内存中,所以不需要事先申请空间存储,同时不需要考虑容量问题。
- 插入删除效率较高。
- 链表只记录第一个节点和最后一个节点,所以随机访问较慢。
- ArrayList:借助于数组实现,允许存放空值。(Vector是线程安全的ArrayList)
- Set:无序的,不允许存放重复值且最多允许一个null值,不提供通过index访问元素的操作。
- java.util.Map:存放key=value映射的集合。给每一个value赋一个唯一的标识符。所以key值不能重复,只能对应一个value。
- HashMap:借助于HashTable实现的Map集合,允许存在null的key值和null的value值。
- HashTable:线程安全的HashMap且不允许存在null值。不保证数据的迭代顺序,不保证数据的永久储存。
- SortedMap:要求存放在SortedMap集合中的所有key值应该拥有自然排序规则(implements Comparable)或者能够按照创建SortedMap集合时传递的Comparator进行排序。
- TreeMap:SortedMap的直接实现。
三. 增强for循环:foreach jdk5.0
- 语法:
for(DataType varName;Collection/Array)
- varName:用来接收数组/集合中的每一个数据元素。
- 如果一个对象能够使用增强for循环的语法来遍历所有数据,对象必定实现了Iterator方法。作为增强for循环,它最终被编译器编译为借助于Iterator实现的迭代过程。
四. 泛型
- 将类型参数化,可以再编译时阻止用户的非法输入,在运行时尽可能少的抛出ClassCastException;
- 语法: