面向对象的核心:
设计对象来处理数据,解决问题。
一、静态
static读作静态,可以用来修饰成员变量,也能修饰成员方法。
1.1 static修饰成员变量
Java中的成员变量按有无static修饰分为两种:类变量、实例变量。
类变量:有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享
实例变量(对象的变量):属于每个对象。
由于静态变量是属于类的,只需要通过类名就可以调用:类名.静态变量
实例变量是属于对象的,需要通过对象才能调用:对象.实例变量
1.2 static修饰成员方法
成员方法根据有无static也分为两类:类方法、实例方法。
有static修饰的方法,是属于类的,称为类方法;调用时直接用类名调用即可。
无static修饰的方法,是属于对象的,称为实例方法;调用时,需要使用对象调用。
演示:
点击查看代码
public class Student{
double score;
//类方法:
public static void printHelloWorld{
System.out.println("Hello World!");
System.out.println("Hello World!");
}
//实例方法(对象的方法)
public void printPass(){
//打印成绩是否合格
System.out.println(score>=60?"成绩合格":"成绩不合格");
}
}
public class Test2{
public static void main(String[] args){
//1.调用Student类中的类方法
Student.printHelloWorld();
//2.调用Student类中的实例方法
Student s = new Student();
s.printPass();
//使用对象也能调用类方法【不推荐,IDEA连提示都不给,就别这么用了】
s.printHelloWorld();
}
}
1.类方法:
static修饰的方法,可以被类名调用,是因为它是随着类的加载而加载的;
所以类名直接就可以找到static修饰的方法
2.实例方法:
非static修饰的方法,需要创建对象后才能调用,是因为实例方法中可能会访问实例变量,而实例变量需要创建对象后才存在。
所以实例方法,必须创建对象后才能调用。
1.3 工具类
如果一个类中的方法全都是静态的,那么这个类中的方法就全都可以被类名直接调用,由于调用起来非常方便,就像一个工具一下,所以把这样的类就叫做工具类。
如:验证码工具类
点击查看代码
public class MyUtils{
public static String createCode(int n){
//1.定义一个字符串,用来记录产生的验证码
String code = "";
//2.验证码是由所有的大写字母、小写字母或者数字字符组成
//这里先把所有的字符写成一个字符串,一会从字符串中随机找字符
String data = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ";
//3.循环n次,产生n个索引,再通过索引获取字符
Random r = new Random();
for(int i=0; i<n; i++){
int index = r.nextInt(data.length());
char ch = data.charAt(index);
//4.把获取到的字符,拼接到code验证码字符串上。
code+=ch;
}
//最后返回code,code的值就是验证码
return code;
}
}
补充一点:工具类里的方法全都是静态的,推荐用类名调用为了防止使用者用对象调用。我们可以把工具类的构造方法私有化。
1.4 static的注意事项
- 类方法中可以直接访问类的成员,不可以直接访问实例成员
- 实例方法中既可以直接访问类成员,也可以直接访问实例成员。
- 实例方法中可以出现this关键字,类方法中不可以出现this关键字。
1.5 代码块
代码块根据有无static修饰分为两种:静态代码块、实例代码块。
代码块:
就是一对大括号
局部代码块:
在方法内部
限制变量的生命周期
构造代码块:
类中方法外
抽取多个构造方法中的共性内容
执行流程:每次创建对象,自动调用一次,优先与构造方法执行
静态代码块:
类中方法外,加上static
作用:加载驱动,对静态成员进行初始化,加载配置文件
执行流程:类加载的时候,自动执行一次,仅此一次
二、继承
继承:extends
就是让一个类,同另外一个类产生父子关系
好处;
子类可以无条件的使用父类的所有【非私有】的成员
私有;子类压根不知道父类有
提高代码复用
注意:
子类可以使用父类成员,反之不行(子类不能使用父类的私有成员)
单继承,多层继承。
方法的重写:Override
子类将父类的方法进行重写
子父类关系中,两个方法声明完全相同,则是方法的重写。
重写是因为父类方法不满足子类需求。
成员访问特点
子类有,会优先使用自己的
没有,就使用父类的
如果子父类有同名的变量(变量使用原则:就近),super. 指向父类(变量,方法都可以调用)
this. 找自己的(局部变量同名)
权限修饰符:
用来修饰变量或者方法被别人访问的权限
public > protected > 默认 > private
同类 √ √ √ √
同包 √ √ √
不同包子类 √ √
不同包不同类 √
访问本类成员:
this.成员变量 //访问本类成员变量
this.成员方法 //调用本类成员方法
this() //调用本类空参数构造器
this(参数) //调用本类有参数构造器
访问父类成员:
super.成员变量 //访问父类成员变量
super.成员方法 //调用父类成员方法
super() //调用父类空参数构造器
super(参数) //调用父类有参数构造器
注意:this和super访问构造方法,只能用到构造方法的第一句,否则会报错。
栗子:
点击查看代码
public class Demo01 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
class Fu{
A a = new A();//实例化A为成员变量
public Fu(){
System.out.println("父类构造方法:无参");
}
}
class Zi extends Fu{
public Zi(){
//调用父类的构造方法是为了对父类进行初始化,创建子类对象时优先初始化父类
//初始化类的时候,一定会优先初始化成员变量
//super()和this()不能同时存在,都只能放在构造器的第一行,只能在构造方法里使用。
//A a = new A();
super();//父类没有无参构造是,收到调用有参构造(对父类初始化)。还可以初始化父类的成员变量
A a = new A();
System.out.println("子类的构造方法");
}
}
class A{
public A(){
System.out.println("A类的无参构造");
}
}
三、多态
多态
同一个事物,在不同时刻,呈现出来的不同形态。
水、水蒸气、冰
多态:可以使用父类来创建子类对象了
提前:
1. 必须要有继承或者实现关系
2. 要有父类引用指向子类对象
Person p = new Student();
Animal a = new Dog();
Animal a = new Cat();
3. 要有方法重写
成员访问特点:
除了成员方法以外,调用的都是父类的成员。
方法可以被子类重写。
好处:
提高代码的扩展和维护性。
方法参数如果是父类,调用方法时,可以传递该父类的所有子类进入方法。
缺点:
不能访问子类特有成员
强制类型转换:
Person p = new Student();
Student s = (Student)p;
关于多态转型问题,最终记住一句话:原本是什么类型,才能还原成什么类型
四、final关键字
最终的-关键字-修饰符
类:
太监类
被能被子类继承
因为该类中的所有方法,都不想被别人重写
方法:
最终的方法
不允许被子类重写
变量: 该变量只能被赋值一次。
变成常量
基本:
其值不可变
引用:
其地址值不可变
地址值不可变,但是对象里面的内容可变
补充知识:常量
在实际运用当中经常使用final来定义常量。先说一下什么是Java中的常量?
- 被 static final 修饰的成员变量,称之为常量。
- 通常用于记录系统的配置信息
点击查看代码
public class Constant {
//常量: 定义一个常量表示名称
//为了方便在其他类中被访问所以一般还会加上public修饰符
//常量命名规范:建议都采用大写字母命名,多个单词之前有_隔开
public static final String POEPLE_NAME = "菜鸟老王";
}
public class FinalDemo2 {
public static void main(String[] args) {
//由于常量是static的所以,在使用时直接用类名就可以调用
System.out.println(Constant.POEPLE_NAME);
}
}
五、抽象
抽象:
在Java中有一个关键字叫abstract,它就是抽象的意思,它可以修饰类也可以修饰方法。
//abstract修饰类,这个类就是抽象类
public abstract class A{
//abstract修饰方法,这个方法就是抽象方法
public abstract void test();
}
类的成员(成员变量、成员方法、构造器),类的成员都可以有。
严父
提供资源给子类使用,同时给子类制定规则(抽象方法)
专门用来被子类继承
特点:
1. 不能创建对象
2. 可以有抽象方法,也可以没有
3. 抽象方法,必须在抽象类中
4. 类中的成员,同其他类完全相同,唯独多了抽象方法
5. 抽象类中的构造方法,为了提供给子类使用,在子类的构造方法中,通过super()去访问抽象类的构造方法
6. 子类必须重写所有抽象方法,要么子类也是一个抽象类
模版方法设计模式:
提供一个方法模版
模板方法模式主要解决方法中存在重复代码的问题
比如A类和B类都有sing()方法,sing()方法的开头和结尾都是一样的,只是中间一段内容不一样。
此时A类和B类的sing()方法中就存在一些相同的代码。
方法模版方法中,调用抽象方法,让子类重写
注意事项:
abstract
final
被final修饰的方法,子类无法重写,抽象方法,要求子类必须重写,相矛盾
private
私有方法子类无法重写
static
静态方法可以通过类名直接调用,而抽象方法没有方法体,调用毫无意义
板方法模式解决了多个子类中有相同代码的问题。具体实现步骤如下
第1步:定义一个抽象类,把子类中相同的代码写成一个模板方法。
第2步:把模板方法中不能确定的代码写成抽象方法,并在模板方法中调用。
第3步:子类继承抽象类,只需要父类抽象方法就可以了
六、接口
接口:
Java提供了一个关键字interface,用这个关键字来定义接口这种特殊结构。
干爹
解决java单继承的问题
一个类中应该拥有什么样的方法,一定要有出处,而接口可以提供父类以外的方法的出处。
给子类制定【规则】提供【扩展】
成员:
jdk 8以前:
静态常量
抽象方法
jdk 8-9以后:
默认方法
public default void show(){}
子类可以直接使用,也可以重写,但是不强制子类重写。
解决接口升级的问题
静态方法
public static void method(){}
必须通过接口名调用
让接口不依赖于子类,可以拥有一些自己的功能
私有方法
private void add(){}
提供给接口中的其他方法使用
定义好接口之后,是不能创建对象的。那接口到底什么使用呢?需要我注意下面两点
- 接口是用来被类实现(implements)的,我们称之为实现类。
- 一个类是可以实现多个接口的(接口可以理解成干爹),类实现接口必须重写所有接口的全部抽象方法,否则这个类也必须是抽象类
使用接口到底有什么好处呢?主要有下面的两点
- 弥补了类单继承的不足,一个类同时可以实现多个接口。
- 让程序可以面向接口编程,这样程序员可以灵活方便的切换各种业务实现。
最后:
1.一个接口继承多个接口,如果多个接口中存在相同的方法声明,则此时不支持多继承
2.一个类实现多个接口,如果多个接口中存在相同的方法声明,则此时不支持多实现
3.一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会有限使用父类的方法
4.一个类实现类多个接口,多个接口中有同名的默认方法,则这个类必须重写该方法。