Collection接口:定义了存取一组对象的方法,其中子接口Set和List分别定义了存储方式. Set 中的数据对象没有顺序且不可以重复. List 中的数据对象有顺序且可以重复. Map接口定义了存储”键(Key)–值(value)映射“的方法. Map根据键对象找键对象,键值不能重复.
ArrayList : 线程不安全,效率高. 底层实现是数组. 查询比较方便,但是插入,删除效率比较低.
LinkedList : 线程不安全,效率高.底层实现是链表.遍历查询慢,插入比较快.
Vector : 线程安全的,效率低. 底层实现也是数组.
HashMap: 线程不安全,效率高
HashTable:线程安全,效率低
Map集合的底层实现: 数组 + 链表
Collection类对象在调用 remove,contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和hashCode方法;对于自定义的类型,需要重写equals和hashCode方法以实现自定义的对象规则.
注意: java中规定,两个内容相同的对象应该有相等的hashCode.
- Set 接口是Collection的子接口,Set接口没有提供额外的方法,Set接口的特性是容器类中的元素是没有顺序的,而且不可以重复。
- Set容器可以与数学中的“集合”的概念相对应。
- JavaEE API中所提供的Set容器类有HashSet,TreeSet等。
概念:泛型就是参数化类型,使用广泛的类型. 起因:数据类型不明确:
- 装入数据的类型都被当做Object对待,从而"丢失"自己的实际类型.
- 获取数据时往往需要转型,效率低,容易产生错误.
作用:
- 安全:在编译的时候检查类型安全
- 省心:所有的强制转换都是自动和隐式的,提高代码的重用率.
泛型类:定义时使用泛型
- 格式:<>
class 类名<字母列表>{
修饰符 字母 属性;
修饰符 构造器(字母){
}
修饰符 返回值类型 方法(字母){
}
}
不能使用在静态属性,静态方法上
-
使用:指定具体类型
- 编译时会进行类型检查;
- 获取数据时不需要强制类型转换.
- 泛型使用时不能指定基本数据类型
-
泛型常见字母
- T Type 表示类型
- K V 分别代表键值中的Key和Value.
- E 代表Element.
- ? 代表不确定的类型
-
泛型方法
- 定义使用:<字母>
修饰符<字母> 返回类型 方法名(字母){
}
要定义泛型方法,只需要将字母放到返回值的前面
public static <T> void test(T t){
System.out.println(t);
}
// extends <==
public static <T extends Closeable> void test(T... a){
for (T temp : a) {
try {
if(null != temp){
temp.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
泛型方法<> 返回类型前面 只能访问对象的信息,不能修改信息
擦除: - 在使用时没有指定具体的类型 - 子类继承时没有指定类型
处理:
- 擦除后不能类型检查
- 一旦擦除之后按Object接收
- 依然存在编译警告,加上Object可以去除,但是有些虎蛇添足
- 冒泡
- 选择
- 插入
- shell
- 堆
- 整数,小数, Integer , Float , Double 直接比较基本数据类型的大小
- 字符 Character 比较的是Unicode编码之差
- 字符串
- 如果其中一个字符串是另一个字符串的起始开始的字符串,返回的是字符串之差
- 否则 返回的就是Unicode码之差
- java.util.Date: 根据日期的长整形数比较
- 所有的方法调用都是在栈中进行的: 栈-->先进后出
- 方法中定义的变量叫做局部变量,定义在方法或者语句中,必须初始化,存放在栈中
- 成员变量: 定义在类中,有默认初始化,随着对象的建立而建立,存放在堆中
- java VM调优
- 堆默认1/4物理内存
- java -X : 查看java飞标准输入帮助
- java -Xmx100m 设置jvm堆空间最大值
- java -Xms100m 设置jvm的堆空间的初始值
- 栈空间默认内存空间1M
- 无限递归
- java -X : 查看java飞标准输入帮助
- java -Xss 2m: 修改栈的大小
- 封装是指隐藏对象的属性和实际细节,仅对外提供公共访问方式.
- 好处:
- 将变量隔离
- 便于使用
- 提高代码重用性
- 提高安全性
- 封装原则:
- 将不需要对外提供的内容都隐藏起来.
- 把属性都隐藏,提供公共方法对其访问.
- 是一个权限修饰符
- 用于修饰成员(成员变量和成员函数)
- 被私有化的成员只能在本类中有效
常用之一:将成员变量私有化,对外提供的get,set方法对其进行访问.提高对数据访问的安全性.
- 函数名和类名相同
- 没有返回值
- 没有具体的返回值
- 如果类没有定义构造函数,jvm分配一个空构造,如果定义了构造函数,没有空构造.
- 可以重载
- 作用: 给对象初始化
注意:默认构造函数的特点,多个构造函数是一重载的形式存在的.
-
代码块:代码中使用单独的{}围起来的内容.
-
构造代码块
- 类的成员之一
- 使用{}包起来的一段代码
- 创建对象时,先于构造函数调用
-
局部代码块
- 方法内定义的代码块
-
静态代码块
- 使用static修饰的代码块,在类的加载时调用一次,以后不能调用.通常放置堆静态成员变量的初始化过程.
- 静态代码块:在类加载期间执行,而且只执行一次
- 静态成员之间可以相互访问,按序执行
- 静态成员不可以访问非静态成员.
- 非静态成员可以访问静态
- 静态成员通过类访问(和对象无关)
- 构造代码块
- 从上到下按序执行
- 构造函数
- 成员变量
- color = null;
- color = "black";
- 构造代码块
- 构造函数
main方法为什么是静态的? 如果main不是静态的方法,那就是非静态的方法,静态的方法只能通过对象来调用,因此我们必须创建对象,创建对象,需要使用new关键字来创建,但是new对象只能在方法中创建,所以就出现了死循环,main方法只能是静态的.
- pojo: plain old java object
class Dog{
private String color;
public String getColor(){
return color;
}
public void setColor(String color){
this.color = color;
}
}
- 指向对象自身的引用,类似成员变量,使用private修饰.
- this代表本类对象的引用
什么 时候使用this关键字? 当在函数内需要用到调用该函数的对象时,就用this.
this() 访问当前类的构造函数 this()的调用必须是第一条语句. 为了构造函数的重用
super() 访问超类的构造函数 必须是第一行代码. 构造函数的首行要么是this(),要么是super(); super.xxx()访问的是超类的方法 super代表父类的内存空间的标识.
- static关键字:
- 用于修饰成员(成员变量和成员函数)
- 被修饰后的成员具备以下特点:
- 随着类的加载而加载
- 优先于对象存在
- 被所有对象所共享
- 可以直接被类名调用
- 使用注意
- 静态方法只能访问静态成员变量
- 静态方法中不可以写this,super关键字
- 主函数是静态的
继承的概述
- 多个类中存在相同属性和行为是,将这些内容抽取到单独一个类中,那么多个类无需在定义这些属性和行为,只需要继承那个类即可.
- 多个类可以称为子类,单独这个类称为父类或者超类.
- 子类可以直接访问父类中的非私有的属性和行为.
- 通过extends关键字让类与类之间产生继承关系
class SubDemo extends Demo{ }
- 继承的出现提高了代码的复用性.
- 继承的出现让类与类之间产生了关系,提供了多态的前提.
继承的特点
- java只支持单继承,不支持多继承.
- 一个类只能有一个父类,不可以有多个父类.
- java支持多层继承(继承体系)
class A{ }
class B extends A{ }
class C extends B{ }
- 定义继承需要注意:
- 不要仅为了获取其他类中某个功能而去继承
- 类与类之间要获取("is a")关系, xx1是xx2的一种.
- 子类中出现于父类一样的方法时,会出现覆盖操作,也称为重写或者复写.
- 父类中的私有方法不可以被覆盖
- 在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取.
- 覆盖注意事项:
- 覆盖时,子类方法权限大于等于父类方法权限
- 静态只能覆盖静态.
- 覆盖的应用:
- 当子类需要父类的功能,而功能主体有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容.
- final 可以修饰类,方法,变量.
- final 修饰的类不可以被继承.
- final修饰的方法不可以被覆盖;
- final 修饰的变量时一个常量.只能被赋值一次.
- 内部类只能访问被final修饰的局部变量.