目录
一、类和对象
1. 定义类
//创建类
class ClassName{ // 大驼峰写类名
field; // 字段(属性)或者 成员变量
method; // 行为 或者 成员方法
}
注: (1) public 修饰的类必须要和文件名相同
(2) main方法所在类用public修饰
2. 类的实例化
用类类型创建对象-->类的实例化
new 类名()
注: (1)new关键字用于创建一个对象的实例
(2)使用 . 号来访问对象中的属性和方法
3. this引用
Def:指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。
特性:
(1)this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
(2)this只能在“成员方法”中使用
(3)在“成员方法”中,this只能引用当前对象,不能再引用其他对象
使用:
this.成员变量;
this.成员方法;
this();//访问构造方法
4. 对象的初始化
Date d = new Date(); //初始化对象
(1)构造方法
<1>名字与类名相同,没有返回值类型,void也不行
<2>public修饰
<3>创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
<4>作用:对对象中的成员进行初始化,并不负责给对象开辟空间
<5>可以重载
<6>如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法无参。一旦用户自定义了构造方法,编译器则不再生成默认构造方法。
<7>构造方法中,可以通过this调用其他构造方法来简化代码,但this必须在第一句且不能形成环
<8>实例化对象时一定调用构造方法,构造方法调用完成,对象才创建完成
(2)默认初始化:成员变量没有赋值时默认初始化为默认值
(3)就地初始化:成员变量直接赋值
5. 封装
(1)访问限定符:
Java通过类和访问权限实现封装:类可以把数据以及封装数据的方法结合在一起,访问权限用来控制方法或者字段能否直接在类外使用。限定类或者类中成员能否在类外或者其他包中被访问。
No | 范围 | private | default | protected | public |
1 | 同一包中的同一类 | √ | √ | √ | √ |
2 | 同一包中的不同类 | √ | √ | √ | |
3 | 不同包中的子类 | √ | √ | ||
4 | 不同包中的非子类 | √ |
(2)包:对类、接口等进行组织
在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
导入包中的类:import 语句
自定义包:在文件的最上方加一个package语句指定该代码在哪个包中,包名指定为代码路径
6. static成员
被static修饰的成员,称之为静态成员,也称为类成员,其不属于某个具体的对象,是所有对象所共享的。
(1)static修饰成员变量
<1>可以通过对象/类名访问,推荐使用类名访问
<2>类变量存储在方法区中
<3>生命周期伴随类的一生
(2)static修饰成员方法
<1>通过静态方法访问,也就是通过 类名.静态方法名(...) 调用
<2>不能在静态方法中访问任何非静态成员变量
<3>静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用的时候无法传递this引用
<4>静态方法无法重写,不能实现多态
(3)static成员变量初始化
就地初始化:在定义时直接给出初始值
静态代码块初始化
7. 代码块:使用{}定义的一段代码
普通代码块、构造块、静态块、同步代码块
(1)构造代码块(实例代码块)---初始化实例成员变量,创建对象时才会执行
(2)静态代码块:初始化静态成员变量
注: <1>静态代码块不管生成多少个对象,其只会执行一次
<2>静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
<3>如果一个类中包含多个静态代码块,编译时会按照定义的先后次序依次执行
8. 内部类
(1)内部类的分类
<1>成员内部类(普通内部类:未被static修饰的成员内部类 和 静态内部类:被static修饰的成员内部类)
<2>局部内部类(不谈修饰符)、匿名内部类
(2)实例内部类
<1>可以直接访问外部类中任意访问限定符修饰的成员
<2>外部类和实例内部类中具有相同名称成员时,优先访问内部类自己的
<3>外部类不能直接访问实例内部类的成员,要访问实例内部类中的成员,必须要创建实例内部类的对象
<3>要访问外部类同名成员时,外部类名称.this.同名成员名字
<5>创建实例内部类对象时必须借助外部类
<6>实例内部类中不能有静态的成员变量,非要有就只能是static final修饰
(3)静态内部类
<1>只能访问外部类的静态成员。访问外部类的非静态成员需要通过外部类的对象的引用才能访问
<2>创建静态内部类对象时,不需要先创建外部类对象
(4)局部内部类(少用)
<1>只能在所定义的方法体内部使用
<2>不能被public、static等修饰符修饰
<3>编译器也有自己独立的字节码文件,命名格式:外部类名字$内部类名字.class
9. 对象的打印
使用编译器重写toString:IDEA右键Generate(生成)点击后选择重写的属性,OK即可自动重写。
二、继承和多态
1.继承
(1)概念
共性抽取,实现代码复用;实现多态
(2)语法
修饰符 class 子类 extends 父类 {
//...
}
注: <1> 子类会将父类的成员变量和成员方法继承到子类中
<2> 子类继承父类后,必须新添加自己特有的成员,否则体现不出与父类的继承,就没必要使用继承。
(3)子类、父类的成员访问
<1> 子类访问成员变量:就近原则,看有无,如果子类有优先自己,如果无则看父类,如果父类也没有编译器就会报错。(注:同名则优先访问自己的)
<2> 子类访问成员方法:同访问成员变量(注:如果同名且构成了重载就看参数列表)
(4)super关键字
作用:在子类方法中访问父类的成员
super.data; //访问父类的成员变量
super.func(); //调用父类的成员方法
super(); //调用父类的构造方法
注: <1> 只能在非静态方法中使用
<2> 在子类方法中,访问父类的成员变量和方法
(5)子类构造方法
<1> 子类对象构造时,需要先调用父类构造方法,然后执行子类的构造方法。
<2> 父类构造方法有参时,需要为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
<3>子类构造方法中默认会调用父类的无参构造方法:super();,没有写的时候编译器会自动添加,而且super()必须在子类构造方法中的第一条语句,并且只能出现一次。
<4>super()在子类构造方法中只能出现一次,并且不能和this同时出现。
(6)super和this的区别
<1> 继承类的构造方法中一定有super()的调用,this如果不写就没有
<2> super关注父类;this关注当前类、当前对象
(7) 再谈初始化
【1】 没有继承关系时,代码块的执行顺序:
<1> 静态代码块先执行,并且只执行一次,在类加载阶段执行
<2> 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行
【2】 有继承关系时,代码块的执行顺序:
<1> 父类静态代码块优先于子类静态代码块执行,且是最早执行
<2> 父类实例代码块和父类构造方法紧接着执行
<3> 子类的实例代码块和子类的构造方法紧接着在执行
<4> 第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
(8)final关键字
【1】 修饰变量或者字段,表示常量(即不能修改)
【2】 修饰类:表示此类不能被继承
【3】 修饰方法:表示该方法不能被重写
(9)继承与组合
继承--->对象之间is-a;组合--->对象之间has-a
2. 多态
(1)概念
不同对象完成同个行为表现出不同的状态。
同一件事情,发生在不同对象身上,产生不同的结果。
(2)多态实现条件
【1】必须在继承体系下
【2】子类必须要对父类中的方法进行重写
【3】通过父类的引用调用重写的方法
多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。
(3)重写
重写(override),是子类对父类非静态、非private修饰、非final修饰、非构造方法等的实现过程进行重新编写,返回值和形参都不能改变。
好处:子类可以根据父类需要,定义特定于自己的行为。也就是说,子类能够根据需要实现父类的方法。
【1】 方法重写的规则
<1> 子类在重写父类的方法时,一般必须与父类方法原型一致:返回值类型 方法名 (参数列表) 要完全一致
<2> 被重写的方法返回值类型可以不同,但是必须是具有父子关系的
<3> 访问权限不能比父类中被重写的方法的访问权限更低。
<4> 父类被static、private修饰的方法、构造方法都不能被重写
<5> 重写的方法,用@Override注解来显式指定,可以帮助我们进行合法性校验。
【2】 重写和重载区别
区别点 | 重写 | 重载 |
参数列表 | 一定不能修改 | 必须修改 |
返回类型 | 一定不能修改【除非可以构成父子类关系】 | 可以修改 |
访问限定符 | 一定不能做更严格的限制(可以降低限制) | 可以修改 |
即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
(4)向上转型和向下转型
【1】向上转型:创建一个子类对象,将其当成父类对象使用
Animal animal = new Cat();
animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。
使用场景:
<1> 直接赋值:子类对象赋值给父类对象
<2> 方法传参:形参是父类型引用,可以接收任意子类的对象
<3> 方法返回:返回任意子类对象
优点:让代码实现更简单灵活;缺陷:不能调用到子类特有的方法
【2】向下转型:将父类引用还原为子类对象(少用,可使用instanceof提高向下转型的安全性)
(5)另
一个引用 调用同一个方法,因为这个引用 引用的对象不一样,导致调用这个方法,所表现的行为不一样,这种思想,就叫做多态。
三、抽象类和接口
1. 抽象类
(1)概念
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
存在意义:为了被继承
(2)语法
//抽象类:被abstract修饰的类
public abstract class Shape {
//抽象方法:被abstract修饰的方法,没有具体实现
abstract public void draw();
abstract void calcArea();
//抽象类也是类,也可以增加普通方法和属性
public double getArea() {
return area;
}
protected double area;// 面积
}
注:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法
(3)特性
【1】不能直接实例化对象,不能new;
【2】不能是private的。没有加访问限定符时,默认是public;
【3】抽象方法不能被final(和abstract矛盾了)和static修饰,因为抽象方法要被子类重写;
【4】抽象类必须被继承,并且继承后子类必须要重写父类中的抽象方法,否则子类也是抽象类,必须用abstract修饰;
【5】抽象类中不一定包含抽象方法,但有抽象方法的类一定是抽象类;
【6】抽象类中有构造方法,供子类创建对象时,初始化父类的成员变量。
2. 接口
(1)概念
多个类的公共规范,是一种引用数据类型
(2)语法规则
与定义类格式基本相同,将class关键字换成interface关键字,即定义了一个接口。
public interface 接口名称 {
//抽象方法
public abstract void method1();//public abstract是固定搭配,可以不写
public void method2();
abstract void method3();
void method4();
//注意:在接口中上述写法都是抽象方法,更推荐写method4,更简洁
}
(3)接口使用
接口不能直接使用,必须要有一个“实现类”来“实现”接口,实现接口中的所有抽象方法。
public class 类名称 implements 接口名称 {
//...
}
注意:子类和父类之间是extends继承关系,类与接口之间是implements实现关系。
(4)接口特性
【1】接口类型是一种引用类型,但是不能new出接口的对象,不能实例化;
【2】接口当中的成员方法,不能有具体的实现。jdk1.8开始允许有可以实现的方法,但是这个方法只能由default修饰。可以实现有一个静态方法;
【3】接口的每一个方法都是public abstract的抽象方法,即接口中的方法会被隐式指定为public abstract(只能是public abstract,其他修饰符都会报错);
【4】接口中的变量会被默认指定为public static final
【5】类和接口之间采用implement实现多个接口
【6】重写接口中方法时,不能使用default访问权限修饰
【7】子类重写抽象方法,必须加上public
【8】接口中不能有静态代码块和构造方法
【9】如果不想实现接口的方法,那么就把这个类定义为抽象类,但是如果这个类 被其他类继承 那么必须重写
【10】一个类可以实现多个接口,使用implement用逗号隔开(解决多继承)
(5)接口间的继承
interface A1{
void func1();
}
interface B1{
void func2();
}
//接口和接口之间
interface D extends A1,B1{
void func3();
}
//类和接口之间
class C1 implement D{
}
(6)抽象类和接口的区别(重要)
抽象类可以包含普通方法和普通字段,这的普通方法和字段可以被子类直接使用(不必重写);
接口中不能包含普通方法,子类必须重写所有的抽象方法
区别 | 抽象类(abstract) | 接口(interface) |
结构组成 | 普通类 + 抽象方法 | 抽象方法 + 全局常量 |
权限 | 各种权限 | public |
子类使用 | 使用extends关键字继承抽象类 | 使用implement关键字实现接口 |
关系 | 一个抽象类可以实现若干接口 | 接口不能继承抽象类,但是接口可以使用extends关键字继承多个父接口 |
子类限制 | 一个子类只能继承一个抽象类 | 一个子类可以实现多个接口 |
3. Object类
所有类的父类。
所有类的对象都可以用Object的引用进行接收。
(1)对象比较equals方法
比较对象中内容是否相同,必须重写Object中的equals方法,因为equals方法默认也是按照地址进行比较的。
(2)hashcode方法
确定对象在内存中存储的位置是否相同