一、static关键字
1.概念
被多个对象“共享、公用”的意思
2.特点
- 被static修饰的成员(变量/方法)随着类的加载而加载,优先于对象存在!
(对象创建: 类名 对象名 = new 类名() ;)
某个类要先被编译产生-->类名.class--->类在运行的时候,加载过程要将静态的成员都先进入方法区的静态区中!
- static和this不能共存!
this:代表是当前类对象的地址值引用---说明对象创建完毕,才能使用this.变量名 -->访问成员变量 (对象成员)
static:随着类的加载而加载,被static修饰的成员--->"类成员"
-
如果有一个变量体现出被共享,被共用—>此时用"static"修饰
-
访问方式:(必须记住)
类成员--->被static修饰的,特有访问 方式
类名.变量名; //在访问本类中静态变量
类名.方法名() ;//在访问本类中的静态方法
注意:
我们所说的成员变量/成员方法---->默认 非静态的!
3.使用注意事项
1)非静态的成员方法里面,皆可以访问静态的变量/方法,也可以访问非静态的变量/方法!
2)静态的方法只能访问静态的成员,不能访问静态的
记住: 静态只能访问静态!
二、final关键字
1.概念
final:是一个状态修饰符 (最终的,无法更改的)
2.特点
基本概念:最终的/无法更改的
1)修饰类,该类不能够被继承!(当前这个类是最终类,无法来提供派生类(子类))
2)修饰成员方法,该成员方法不能重写(保证父类的方法安全性!)
3)修饰变量,此时该变量一个常量,不能在重新赋值!
3.问题
final修饰基本数据类型和修饰引用数据类型的区别?
final修饰的引用数据类型,当前不能在开辟堆内存(不能重新new),里面的成员变量依然可以进行赋值
final修饰的基本数据类型,基本数据数据值不能在改变!
提供无参构造方法,无参构造私有化—目的就是为了让外界类不能创建对象!private ArrayTool(){}
三、常量
编译时期常量---->基本数据类型:四类八种 (jvm不需要加载)
public static final int a = 10 ;
运行时期常量---->引用数据类型: (jvm进行加载,引用类型 除过String)
int类型--->包装类 类型 Integer类
public static final Integer i = new Integer(10) ;
//i = new Integer(100) ;//报错
开发中自定义常量:
public static final 数据类型 变量名 = 初始化值;
四、代码块
1.概念
Java中的代码块是一个{}包裹起来的内容!
2.分类
- 局部代码块—>方法定义中
作用:限定局部变量的生命周期
- 构造代码块—>类的成员位置定义的{}
作用:在执行构造方法之前,如果存在构造代码块,先执行构造代码块,然后在执行构造方法,就是给数据进行初始化的!
- 静态代码块—>类的成员位置定义的
static{
}
特点:跟类相关,类一加载,先执行,而且只执行一次(因为类就加载一次)
优先级最大
3.优先级
静态代码块 > 构造代码块 > 构造方法!
五、继承
1.概念
将多个类的共性内容抽取到一个独立的类中,这个独立的类和这多个类产生一种关系 "继承"
2.格式
class 父类名{}
class 子类名 extends 父类名{}
3.继承的好处
1)可以提高代码的复用性
2)可以增强代码的后期维护
3)类与的类关系:继承关系 是多态的前提条件!
4.使用继承的前提条件
如果一个类A是类B一种,或者是类B是类A的一种,才能使用继承,继承的核心思想体现出一种"is a"的关系
5.继承的特点
1)在Java语言中,类与类的关系,只支持单继承 (类是Java中最基本的单元)
举例:
class Fu{}
class Fu2{}
class Zi extends Fu,Fu2{} 这种写法错误格式
2)类与类之间虽然不支持多继承,但是可以多层继承!
6.继承的注意事项
1)子类继承父类,是可以继承父类所有的东西,只不过父类的私有的属性以及方法只能在本类中访问,子类是不能直接访问到的,但是可以间接的通过公共方法来访问!
2)子类继承父类,不能继承父类的构造方法(无参/有参构造),可以通过 "super"来访问父类的构造方法!
7.问题
一个类的成员:
成员变量
成员方法
构造方法
1.子类继承父类,子类中 成员变量如果父类中的成员变量名称不一致的情况
比较简单,分别访问即可!
2.子类继承父类,如果子类的成员变量名称和父类的成员变量名称一致,如何访问呢?
a)先在子类的局部位置(子类的成员方法中定义变量:局部变量)找,如果存在,就使用
b)如果子类的局部位置没有,然后才在子类的成员位置找,如果存在,就使用
c)如果子类的成员位置没有,然后在父类的成员位置找,如果存在,就使用
d)如果父类的成员位置也没有,说明当前没有这个变量,就访问报错!
一句话:就近原则!
3.子类继承父类,子类如何访问父类的构造方法? ----通过super关键字
1)子类继承父类,不能继承父类的构造方法,但是可以通过super访问,子类的所有构造方法默认访问父类的无参构造方法!
子类的构造方法的第一句话:都有super() ; 访问父类的无参构造方法
原因:
子类继承父类,可能用到父类的属性(成员变量)这些数据,必须让父类先初始化,然后子类才能初始化(构造方法,就是给数据初始化的)
这种过程----继承中 "分层初始化"
2)永远建议把父类的无参构造方法给出来,可能会导致子类的构造方法报错!
4.如果父类中并没有给出无参构造方法,子类会出现什么情况?如何解决?
子类的所有构造方法都会报错!默认都要访问父类无参构造方法(默认机制)
解决方案:
1)自己手动给出父类的无参构造方法(推荐)
2)不给出父类的无参构造方法,怎么解决?
让子类的所有构造方法都直接来访问父类的有参构造方法,只要父类初始化即可!
3)所有的子类的构造方法只要有一个让父类初始化即可!
在子类的无参构造方法中第一句话: this(xxx) ; 访问本类(子类)的有参构造方法
在通过子类的有参构造方法的第一句话:super(xxx) ;访问父类的有构造方法---->父类先初始化完毕
实际开发中:(写继承代码的时候)
子类继承父类,子类的无参构造方法访问父类的无参!
子类的有参构造方法访问父类的有参!
实际开发中
所有的开发原则都必须遵循 "低耦合,高内聚"
耦合:类和类的关系越少越好,耦合性只能降低,不能避免!
内聚:解决某件事情(功能)的执行力!(一个类能够完成的尽量一个类完成,不能产生过多关系!)
六、多态
1.概念
从宏观角度去说:一个事物(能看到真实存在的)体现出的不同形态!
举例:
水--->固态 气态 液态
从内存角度去说:一个对象它的所在的类型的变化
举例:
Cat c = new Cat() ; //创建一个只猫 从右边--->左边:猫是猫
Animal a = new Cat() ; //堆内存是猫 从右边--->左边:猫是动物
2.前提条件
1)必须存在继承关系,才能使用多态
2)必须存在方法重写,子类继承父类,部分功能将父类进行重写,比如:
动物都要吃和睡,具体的动物类:猫/狗/猪,吃和睡的动作不一样
3)必须存在父类引用指向子类对象 ----->多态的 "向上转型"
class 父类名{}
class 子类名 extends 父类名{}
//多态测试---
父类名 对象名 = new 子类名() ;
3.多态的好处
1)可以提供代码的复用性(由继承保证的)
2)可以提高代码的扩展性(健壮性)--->由多态保证
4.多态的成员访问特点
成员变量:编译看左,运行看左!
成员方法(默认都是非静态): 如果子类重写了父类的方法,编译看左,运行看右!
静态方法算不上重写,和静态的都是类成员! (访问方式都是类名来调用的)
构造方法:继承是多态的前提条件,所以在使用父类引用指向子类对象:Fu fu = new Zi() ;
还是要遵循"分层初始化",先让父类构造初始化,然后在是子类构造初始化!
5.多态的弊端
多态的弊端:不能访问子类特有方法,通过向下转型来访问,这种方式节省内存;
但是向下转型使用不当,会出现运行时期的异常
"向下转型"---->强转类型转换的格式 ,前提必须有"向上转型"
数据类型 变量名 = (目标数据类型)(初始化值或者表达式) ;
七、抽象类
1.抽象
仅仅给出方法的声明---->含义没有方法体{},抽象功能---->
有抽象的方法的必须为抽象类
抽象类中不一定都是抽象方法!(部分的功能,抽象功能,必须让子类必须重写!)
2.abstract关键字
abstract:用在类上,标记这个类----抽象类
用在方法上,标记这个方法是一个抽象方法!
结合public使用居多
3.抽象方法(成员方法)的格式
权限修饰符 abstract 返回值类型 方法名(空参/带参) ;
4.抽象类的本质
强制子类必须将父类的所有的抽象方法,必须实现(重写)
5.抽象类的特点
1)不能实例化(不能new 创建对象)
2)抽象类的子类一定有具体类,否则无法进行实例化的!
6.抽象类的成员特点
1)成员变量:
可以是变量也可以自定义的常量
2)成员方法
既可以有抽象方法,也可以有非抽象方法!
3)构造方法
还存在继承关系,分层初始化--->先父类构造初始化,然后是子类构造初始化!
无参构造方法/有参构造方法都可以存在,目的都是为了数据进行初始化!
7.问题
1.抽象abstract关键字不能和哪些关键字共存?
abstract不能和private共用:
被private修饰的只能在当前类访问,而abstract修饰的方法,它需要强制子类进行重写;
abstract不能和static共用:
abstract修饰的成员方法,需要被子类重写,还是抽象类多态进行实例化Fu fu = new Zi() ;
而static随着类的加载而加载(静态方法算不上重写),跟类相关的!
abstract不能和final共用:
被final修饰的成员方法不能被重写,而abstract修饰的成员方法,强转子类重写!
八、接口
1.概念
接口体现的是这个事物本身不具备的功能,是一种额外的扩展功能!
只要这个事物实现了接口,它就具备这个功能!
2.接口的特点
1)接口不能实例化(不能创建对象)
2)接口如何实例化?
接口多态
接口名 对象名 = new 接口的子实现类名() ; (前提:子实现类是非抽象的,就是一个具体类)
3.接口中的成员特点
成员变量:只能是常量 存在默认修饰符 public static final
成员方法:(非静态):只能是抽象方法,存在默认修饰符 public abstract
在接口中是可以定义静态方法,必须有方法体(特例)
构造方法: 没有构造方法! 因为子实现类和接口的关系是implements实现关系,只是将接口暴露的额外功能进行实现!
九、关系
在Java中,
类与类:
继承关系,extends,而且只支持单继承,不支持多继承,但是可以多层继承!
类与接口
实现关系,implements,而且一个类继承另一个类的同时,是可以实现多个接口的!接口名和接口名直接逗号隔开
class LoverImpl extends Lover implements Love,Study{
接口与接口
继承关系,extends,不仅支持单继承,也支持多继承,也可以多层继承!
十、方法的形参和返回值
1.形参
方法的形式参数问题: 只研究引用类型
方法形式参数:
具体类:调用该方法,此时实际参数需要的是当当前类的对象!
抽象类:调用该方法,此时实际参数需要的是当前抽象类的子类对象!
接口类型:调用该方法,此时实际参数需要的是接口的子实现类对象!
开发中:方法形式参数是具体类以及接口情况居多的!
2.返回值
研究的方法的返回值引用类型:
方法的返回值如果是引用类型:
具体类:需要返回该具体类的对象!
抽象类:需要返回该抽象类的子类对象!
接口:需要返回接口子实现类对象!
十一、权限修饰符的范围
同一个包下的同一个类中 | 同一个包下的子类中/同一个包下的无关类中 | 不同包下的子类中 | 不同包下的无关类中 | |
---|---|---|---|---|
private:私有 | Y | |||
默认修饰符 | Y | Y | ||
protected:受保护的 | Y | Y | Y | |
public:公共的/公开的 | Y | Y | Y | Y |
十二、内部类
1.概念
在Java中,在一个类中定义另一个类:
举例
在类A中,定义一个类B,将类B称为类A的内部类,类A是类B的外部类!
2.成员内部类
成员内部类:在类中,方法外定义的类
特点:
可以访问外部类的成员包括私有!
直接去访问外部类的中的成员内部类的成员方法:特有方式 (成员内部类没有private以及static修饰!)
外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
成员内部类可以使用过static修饰:
特点:静态的成员内部类它里面的所有 成员方法:
无论是静态的方法还是非静态的,访问外部类的成员:必须先为静态
想直接去访问静态的成员内部类的这些成员方法:??
外部类名.内部类名 对象名 = new 外部类名.内部类名();
3.局部内部类
局部内部类:在外部类的成员方法中定义的类
特点:
局部内部类也是可以直接访问外部类的成员变量,包括私有!
匿名内部类:(没有名字的类)---是内部类的一种简化格式!
针对抽象类或者接口去使用的
匿名的格式
new 类名(抽象类)或者接口名(){
重写类里面或者接口的抽象功能!
} ;
应用范围:在局部位置中使用
匿名内部类的本质:
是继承了该抽象类或者是实现了接口子类对象!
1)局部内部类里面的成员在访问局部变量的时候,局部变量有什么要求?
局部内部类在访问外部类的成员方法中的局部变量的时候,此时局部变量必须加入final修饰!
原因:
局部变量的生命周期随着方法调用而存在,随着方法调用结束而消失;
外部类的成员方法调用完毕,此时这个局部变量应该释放了,但是当前这个成员方法中创建局部内部类对象
使用局部内部类对象访问它里面的成员方法,成员方法还在使用这个局部变量,所以此时这个变量为常量,显示的加入final修饰