记录时间:2020年7月30日
学习书籍:《实战Java程序设计》《实战Java程序设计》微信读书电子版
配套视频:《Java课程300集》
一、面向对象
普通类、抽象类和接口的区别如下:
■ 普通类:具体实现。
■ 抽象类:具体实现,规范(抽象方法)。
■ 接口:规范。
1.抽象方法和抽象类
抽象方法使用abstract修饰的方法,没有方法体,只有声明。它定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现。
包含抽象方法的类就是抽象类。抽象类通过abstract方法定义规范,要求子类必须定义具体实现。通过抽象类可以严格限制子类的设计,使子类之间更加通用。
抽象类的使用要点如下:(1)有抽象方法的类只能定义成抽象类。(2)抽象类不能实例化,即不能用new来实例化抽象类。(3)抽象类可以包含属性、方法和构造器,但是构造器不能用new来实例化,只能用来被子类调用。(4)抽象类只能用来被继承。(5)抽象方法必须被子类实现。
package com.abs
abstract class Animal1 {
abstract public void shout();//抽象方法
}
//抽象类
class Dog extends Animal1{
//子类必须实现父类的抽象方法
public void shout(){
System.out.println("wang wang");
}
public void seeDoor(){
System.out.println("看门中");
}
}
//测试抽象类
public class Animal{
public static void main(String[] args){
Dog a=new Dog();
a.shout();
a.seeDoor();
}
}
2.定义和使用接口
比抽象类还抽象的“抽象类”,实现规范和具体实现的分离。
接口的声明格式:[访问修饰符] interface 接口名 [extedns父接口…]{}
定义接口的详细说明如下:
■ 访问修饰符:只能是public或默认设置。
■ 接口名:和类名采用相同的命名机制。
■ extends:接口可以多继承。
■ 常量:接口中的属性只能是常量,总是以public static final修饰,不写也是。
■ 方法:接口中的方法只能是public abstract,即使省略,也还是public abstract
要点:
■ 子类通过implements来实现接口中的规范。■ 接口不能创建实例,但是可用于声明引用变量类型。■ 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。■ 在JDK1.7之前的版本中,接口中只能包含静态常量和抽象方法,不能有普通属性、构造器和普通方法。■ 在JDK1.8之后的版本中,接口中包含普通的静态方法。
package com.abs;
public class TestInterface {
public static void main(String[] args){
Angel a=new Angel();
a.fly();
Volant v=new BirdMan();
v.fly();
}
}
interface Volant{
/**总是public static final类型的*/
int FLY_HIGHT=100;
void fly();//总是:public abstract void fly()的
}
/**善良接口*/
interface Honest{
void helpOther();
}
/**Angel类实现飞行接口和善良接口*/
class Angel implements Volant,Honest{
public void fly(){
System.out.println("我正在飞");
}
public void helpOther(){
System.out.println("帮助人");
}
}
class BirdMan implements Volant{
public void fly(){
System.out.println("鸟人也会飞");
}
}
3. 内部类
内部类是一种特殊的类,它指的是定义在一个类的内部的类。为了方便使用外部类的相关属性和方法,通常需要定义一个内部类。
内部类可以使用public、default、protected 、private以及static来修饰,而外部顶级类(前面接触的类)则只能使用public和default来修饰。
package com.abs;
class Outer{
private int age=10;
public void show(){
System.out.println(age);
}
public class InnerClass {
private int age=20;
public void show(){
System.out.println(age);
}
}
}
四. static关键字
在实际开发时,开发人员有时会希望在不创建对象的情况下就可以调用某个方法,换句话说也就是使该方法不必和对象绑在一起。要实现这样的效果,只需要在类中定义的方法前加上static关键字即可,通常称这种方法为静态方法。同静态变量一样,静态方法可以使用“类名.方法名”的方式来访问,也可以通过类的实例对象来访问。
注意:在一个静态方法中只能访问用static修饰的成员,原因在于没有被static修饰的成员需要先创建对象才能访问,而静态方法在被调用时可以不创建任何对象。
五.容器
由于数组并不能满足人们对于“管理和组织数据的需求”,所以需要一种更强大、更灵活、可随时扩容的容器来装载对象,这就是本章要介绍的容器,也称作集合(Collection)。
image.png
在类的声明处可以增加泛型列表,如<T, E, V>。
Collection表示一组对象,它是集中或收集的意思。Collection接口的两个子接口是List与Set接口。
List是指有顺序、可重复的容器。
List接口常用的实现类有3个:ArrayList、LinkedList和Vector。
ArrayList的底层是用数组实现存储的,其特点是查询效率高,增删效率低,线程不安全。
LinkedList底层用双向链表来实现存储,其特点是查询效率低,增删效率高,但线程不安全。
Vector底层是一个长度可以动态增长的对象数组,它的相关方法都进行了线程同步,因此“线程安全,效率低”
如何选用ArrayList、LinkedList和Vector?■ 需要线程安全时,用Vector。■ 不存在线程安全问题并且查找较多时,用ArrayList(一般使用它)。■ 不存在线程安全问题,但增加或删除元素较多时,用LinkedList。
Map就是用来存储“键(key)—值(value)”对的
image.png
HashMap采用散列算法来实现,它是Map接口最常用的实现类。由于底层采用哈希表来存储数据,因此要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。HashMap在查找、删除、修改方面的效率都非常高。
HashTable类和HashMap用法几乎一样,底层实现也几乎一样,只是HashTable的方法添加了synchronized关键字以确保线程同步检查,效率较低。
HashMap与HashTable的区别■:
HashMap:线程不安全,效率高。允许key或value为null。■ HashTable:线程安全,效率低。不允许key或value为null。
TreeMap是红黑二叉树的典型实现。
SET
Set接口继承自Collection, Set接口中没有新增方法,方法和Collection保持完全一致,前面通过List学习到的方法,在Set中仍然适用
Set容器的特点是无序、不可重复。无序指Set中的元素没有索引,只能通过遍历方式查找;不可重复指不允许加入重复的元素。
Set常用的实现类有HashSet和TreeSet等,一般使用HashSet。
TreeSet的底层用TreeMap实现,其内部维持了一个简化版的TreeMap,并通过key来存储Set的元素。TreeSet内部需要对存储的元素进行排序,因此,对应的类需要实现Comparable接口
使用TreeSet应注意以下两点:
(1)由于TreeSet底层是一种二叉查找树(红黑树),需要对元素做内部排序。如果要放入TreeSet中的类没有实现Comparable接口,则会抛出异常java.lang.ClassCastException。(2)TreeSet中不能放入null元素。
Iterator接口
Iterator接口可以让开发者实现对容器中对象的遍历。
Collections工具类
java.util.Collections类提供了对Set、List、Map进行排序、填充、查找元素的辅助方法:
■ void sort(List):对List容器内的元素排序,排序的规则是按照升序排序。
■ void shuffle(List):对List容器内的元素进行随机排列。
■ void reverse(List):对List容器内的元素进行逆序排列。
■ void fill(List, Object):用一个特定的对象重写整个List容器
。■ int binarySearch(List, Object):对于顺序的List容器,采用折半查找方法来查找特定对象。
Class类:
Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
Class 没有公共构造方法。Class 对象是在加载类时由Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。