文章目录
类与对象
基础概念辨析
- 面向对象的好处: 模块化、信息隐藏、代码重用、易于调试。
- 方法重载overload和方法覆盖override: 重载是多态性的一种,方法名相同,参数不同;覆盖/重写是重写方法体。返回类型不同不属于重载。
- 对象实例化的过程: 对象实体是用类模版创建对象时,新建对象所获得的内存区域。使用new运算符和类的构造方法为新建对象分配内存,为其中的域赋初值,并将这段内存的引用返回给对象变量。
- Java虚拟机的垃圾回收机制: C++中要求程序员跟踪通过new创建的所有对象,不需要时显式地销毁,这样非常容易出错;Java虚拟机的垃圾回收器定期回收已经不再被引用的对象实体所占的内存。但有时垃圾回收会有一定的滞后性,可能导致性能下降。
- static类变量和成员变量: 类变量由static修饰,一个类所有的对象的该类变量都存储在同一内存空间,公用一个类变量;成员变量是对象自己的实例变量副本,存储在成员变量的空间中。类变量可以通过类名或对象实例访问,成员变量只能通过对象实例访问。
- final: 如果一个域被final修饰,就成为常量,该域的值不能被改动,常量不占内存。
- 类方法和成员方法: 一个类中的方法可以相互调用,在方法中可以访问这个类的成员变量。在实例方法中,可以访问实例变量实例方法+类变量类方法;在类方法中不能访问实例变量实例方法,否则可能存在越界访问错误,访问未分配的内存区域。
- 实参和形参: 按值传递基本类型数据参数,传入实参的级别不能高于形参级别(如能将float实参值传给double形参,但不能将float传给int,除非强制类型转换);按值传递引用类型数据参数,是将地址传给函数,在函数中新建的对象赋地址中的值,因此数组、哈希表等引用类型数据在传入函数后是会改变的(但不是地址改变,是地址中保存的值改变),但是String类型比较特殊,传入后是不会改变的,因为String是被final修饰的,要改变只能新开辟一块内存空间,而引用类型数据传参不改变地址值,所以引用的还是原来的String。
- this关键字: 引用当前实例对象,不能在类方法中出现。可用于调用同一个类的其他构造方法,例如Rectangle(int x, int y, int width, int height){…}, Rectangle(int width, int height){this.Rectangle(0, 0, width, height)}
访问权限
访问权限修饰符 | 含义 |
---|---|
public | 公有变量/公有方法:无论在同一个类的内部、同一个包的不同类、不同包中都可以访问 |
private | 私有变量/私有方法:只有本类中创建的类对象可以访问。用于隐藏内部属性,防止非法访问,是封装性的体现。 |
protected | 受保护的变量/方法:不牵涉继承时,protected和无修饰符作用一样;有继承时,子类能访问(同包/不同包)父类的变量/方法 |
无/friendly | 友好变量/友好方法:没有权限修饰符时,默认为包私有访问权限,只有和这个类在同一个包中的类才能访问。 |
嵌套类和内部类
类型 | 含义 |
---|---|
外部类 | 包含嵌套类的类 |
嵌套类 | 在一个类中定义另一个类,是外部类的成员,可以访问外部类的其他成员(包括public/protected/private) |
静态嵌套类 | static,只和外部类相关,和外部类生成的实例对象无关,不能直接访问外部类定义的实例变量和方法 |
非静态嵌套类(内部类) | 内部类与实例相关联,不能定义静态成员;实例化内部类之前必须先实例化外部类 |
/**实例化内部类之前必须先实例化外部类**/
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
包
注意点:
- 包用于避免命名冲突,实现访问控制。
- 使用小写字母命名包,避免和类名或接口名发生冲突。
- 可以以机构的域名作为包名:cn.edu.szu.csse
- Java语言本身的包使用java.或javax.开头
- 使用另一个包中的类,需要import这个包,再调用包中的类和接口。
- Java运行时环境按需加载所需类的字节码,不加载无关的类。
继承与接口
子类和父类
注意点:
- Java只支持单继承。
- 子类会继承父类所有public和protected的成员变量和成员方法。如果子类和父类在一个包中,子类还会继承父类的友好变量/方法。
- 子类不能继承父类的构造方法。
class Son extends Father{}
当子类创建实例对象时,他的所有成员变量都被分配了内存空间,他的志杰父类和所有祖先类成员变量也都被分配了内存空间。子类可以通过从父类继承的方法,访问父类的私有成员。
成员变量隐藏和方法覆盖
子类中如果有与父类成员名称相同的变量,同名的父类成员会被隐藏。子类不能直接访问被隐藏的父类成员,但可以通过从父类继承的方法访问隐藏变量。
class Father{
int house_area = 100;
public void print_father_house_area(){
System.out.println(house_area);
}
}
class Son extends Father{
double house_area = 120.2;
public void print_son_house_area(){
System.out.println(house_area);
}
}
主函数里:
可以son.print_son_house_area得到被覆盖的house_area,
也可以son.print_father_house_area访问父类被隐藏的同名变量house_area。
- 如果子类中的方法与父类中的方法名字、返回类型、参数个数和类型都相同,父类方法被覆盖。覆盖方法的级别不能降低,即父类中是protected的方法,子类中可以定义为public,但不能改为private。
- 如果父类中的方法不想被覆盖,要使用final限定。
- 被声明为final的类不能被继承,例如String类。
super关键字
super的用法:
- “如果子类中的方法与父类中的方法名字、返回类型、参数个数和类型都相同,父类方法被覆盖。”–>但可以使用super关键字访问父类中被隐藏的成员。
- “子类不能继承父类的构造方法。”–>但可以使用super来调用父类的构造方法。(但是这种方法在对象有较多祖先时,会导致一系列有相互继承关系的类被初始化。)
class Son extends Father{
public Son(int age, int sex){
super(age, sex);
}
}
上转型对象:多态性体现
上转型:子类->父类
强制类型转换:父类->子类
Person p = new Student();
对象p是子类Student的对象实例的上转型对象。
上转型对象会失去子类中的部分属性和功能,只保留与父类相同名称的方法和变量。上转型对象从父类模版中寻找成员变量名和成员方法,因此
- 不能通过上转型对象访问子类对象实例中的成员。
- 子类重写过的同名方法,执行的代码是子类中重写的方法体。
- 可以访问父类中被隐藏的成员变量。
抽象类
- 由关键字abstract修饰
- 不能直接new实例化
- 可能包含也可能不包含抽象方法:抽象方法只有声明,没有实现。
- 有抽象方法的类一定是抽象类。
- 抽象类的子类必须具体实现抽象方法,否则该类也要声明为抽象类。
接口
- Java中可以实现多重接口。
- 接口中只能包含常量、方法声明,不能包含方法体。
- 接口只能用于声明变量,不能实例化。
- 接口中的方法默认是public、abstract的->实现类必须具体实现接口的所有方法。
- 接口也可以继承接口,并可以继承多个接口。
接口回调也是多态性的体现:可以把某一个接口类所创建的对象引用赋值给使用过该接口声明的接口变量。
interface Workable{
void working();
}
class Worker implements Workable{
public void working(){
//....
}
}
在主函数中设定:
Workable wkb;
Worker worker = new Worker();
wkb = worker;
wkb.working();//此时调用的就是worker中已实现的方法体。
String / StringBuilder/ StringBuffer
String
StringBuilder / StringBuffer
String对象一旦创建,字符串的长度和内容将不再发生变化。
- 如果对字符串的修改比较频繁,应使用StringBuilder类。
- 如果需要线程安全,应使用StringBuffer类。
作用 | 方法 |
---|---|
长度 | sbd.length() |
容量 | sbd.capacity() |
构造方法1:无参构造 | 无参构造StringBuilder(),创建容量为16的空字符串 |
构造方法2:放入字符序列 | StringBuilder(CharSequence cs),内容与cs相同,尾部添加16个空元素 |
构造方法3:指定初始容量 | StringBuilder(int initCapacity) |
构造方法4:放入字符串 | StringBuilder(String s),尾部添加16个空元素 |
设置字符序列长度 | sbd.setLength(int newLength),如果小于当前字符序列,后面的会被截掉 |
保障最低容量 | sbd.ensureCapacity(int minCap) |
添加内容 | sbd.append(各种数据类型都可以),容量不够时自动增加 |
删除一部分字符 | sbd.delete(int start, int end) |
删除一个字符 | sbd.deleteCharAt(int index) |
插入 | sbd.insert(int offset, 各种数据类型),插入是第二个参数会先转化为string |
替换 | sbd.replace(int start, int end, String s) 或 sbd.setCharAt(int index, char c) |
字符串序列翻转 | sbd.reverse() |
转为字符串 | sbd.toString() |
泛型和集合
Collection和Map是并列关系,Collection容纳一组集合元素,Map提供从键到值的转换。
Collection中的List表达一个有序集合,类似于数组;Set的特点是不能包含重复的元素,最多有一个null元素。
集合类型 | 注意点 |
---|---|
ArrayList | 读取操作多时一般用ArrayList。线程不安全。 |
Vector | 线程安全 |
LinkedList | 需要频繁地增删元素时用LinkedList |
HashSet | 使用较多,读取元素是线性时间,设定容量时需要在扩容和检索开销中取舍 |
ArrayList方法
功能 | 方法 |
---|---|
添加到列表尾部 | add(E e) |
添加到指定位置 | add(int index, E e) |
移除所有元素 | clear() |
克隆列表 | clone() |
是否包含某元素 | contains() |
确保最小容量 | ensureCapacity() |
获取指定位置元素 | get(int index) |
指定元素的索引 | indexOf() |
是否为空 | isEmpty() |
最后出现的元素位置 | lastIndexOf() |
移除指定位置元素 | remove(int index) |
移除首次出现的某元素 | remove(Object o) |
移除某范围的元素 | removeRange(int idx1, int idx2) |
用指定元素替代某元素 | set(int index, E element) |
列表元素数 | size() |
返回该列表包含的所有元素的数组 | toArray() |
LinkedList在以上基础之上,多了addFirst(), getFirst(), removeFirst(),addLast(), getLast(), removeLast()(增删查)
TreeSet
TreeSet是一个有序集合,使用元素的自然顺序对元素进行排序,或根据创建set时提供的Comparator进行排序(实现Comparator接口)。
- String按字段顺序排列,标点在前,大写字母在后,小写字母在最后
- compareTo()中比较int类型用return this.age - age;(从大到小排列),比较String类型用this.name.compareTo(name)
HashMap
- HashMap<K,V>允许使用null键和null值。
- 不保证映射顺序,不保证顺序不变。
- 加载因子和初始容量会影响HashMap的性能:初始容量时哈希表在创建时的容量;加载因子是HashMap在容量自动增加前最多可以到达多少比例的尺度,当哈希表数量超过加载因子*当前容量时,哈希表进行重建哈希操作。
- 如果迭代性能很重要,就不应该将初始容量设置地过高或将加载因子设置地过低。