1、继承
//有时不同类之间有共性的东西,如下的name和age
class Student
{
String name;
int age;
void study()
{
System.out.println("study");
}
}
class Worker
{
String name;
int age;
void work()
{
System.out.println("work");
}
}
/*
继承:将不同类之间的通行描述提取出来,单独描述,关键字extends
只要让学生和工人与单独描述的这个类有关系,就可以了
优点:提高了代码的复用性,让类与类之间产生了关系,有了这个关系,才有了多态的特性
注意:千万不要为了获得其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承,所属关系is a 。
另外:Java中,只支持单继承,不支持
多继承(一个子类只能有一个父类)。因为多继承容易带来安全隐患,当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定调用哪一个。但是java保留 了这种机制,并用另一种体现形式来完成表示,多实现。
java支持
多层继承(祖-父-子--孙),也就是一个继承体系。
如何使用一个继承体系中的功能?
想要使用体系,先查询体系父类的描述,因为父类中定义的是该体系中共性功能。通过了解共性功能,就可以知道该体系的基本功能。那么这个体系已经可以基本使用了。那么在具体使用时,要创建最子类的对象,因为有可能父类不能创建对象(如抽象类),创建子类对象可以使用更多功能,包括基本的和特殊的。总结:查阅父类功能,创建子类对象使用功能。
*/
class Person
(
String name;
int age;
)
class Student
extends
Person
{
void study()
{
System.out.println("study");
}
}
class Worker
extends Person
{
void work()
{
System.out.println("work");
}
}
2、聚集:has a
聚合:举例,球员与球队
组合:比聚合关系更紧密,举例:手与人体
3、子父类出现后,类成员的特点:
类中成员:变量,
当子父类中有非私有同名成员变量时,默认使用子类中成员(因为默认的this),如果想在子类对象使用父类成员,使用super,表示父类对象的引用。使用:super.成员
类中成员:函数,
当子父类中有非私有同名函数,叫做重写(覆盖),但此时父类的函数毅然存在。当子类继承父类,沿袭了父类的功能,到子类中。但是子类虽具备该功能,但是功能的内容和父类不一致,这时没有必要定义新功能,而是使用覆盖,保留父类的功能定义,并重写功能。
注意:子类覆盖父类,
必须保证子类权限大于等于父类权限,否则编译失败
静态只能覆盖静态。
重写:子类父类函数名称类型参数必须一模一样,不允许子类中有仅返回值类型不同的同名同参数函数。
重载:只看函数的参数
class Fu
{
void show(){}
void speak()
{
System.out.println("a");
}
}
class Zi extends Fu
{
void speak()
{
System.out.println("b");
}
}
4、子父类中的构造函数,子类构造函数不能覆盖父类的构造函数,因为函数名不同。在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式语句super();,super();在每个子类的构造函数中都有,且调用的是父类中空参数的构造函数。如果父类中没有空参数的构造函数,有带参数的构造函数,则子类构造函数中必须手写
super(参数);,不能默认。
class Fu
{
Fu()
{
System.out.print("fu");
}
}
class Zi extends Fu
{
Zi()
{
//super();该语句为隐的,不写系统会自动加上。调用的是Fu();
System.out.println("zi");
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
Zi z = new Zi();
//结果:fu zi
}
}
为什么子类构造函数一定访问父类构造函数?
因为父类中的数据子类可以直接获取,所以子类对象在建立时需要查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问以下父类中的构造函数,如果要访问父类中指定的构造函数,可以通过手动定义super的参数。在一个构造函数中不能同时存在super和this。
子类的实例化过程
子类所有构造函数,默认都会访问父类中空参数的构造函数,因为子类每个构造函数内的第一行都有一句隐式的super();当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。当然,子类中的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数。
super调用函数:且一定放在子类构造函数的
第一行(第一行,指的是初始化过程先做)。
构造函数:super(参数);
一般函数:super.函数名(参数);
5、final,最终,作为一个修饰符。可以修饰类、函数和变量。
类:被final修饰的类不可以被继承,所以如果不想类被继承,可用final修饰
方法:被final修饰的方法不可以被重写。
变量:被final修饰的变量是常量,只能被赋值一次,既可以修饰成员变量也可以修饰局部变量。当在描述事物时,一些数据的出现值是固定的,那么这时 为了增强阅读性,都会给这些值起个名字方便阅读。而这个值不需要改变,所以加上final修饰,作为常量,常量书写规范:所有字母大写如果由多个单词组成,但此间通过 _ 连接。
另外:内部类定义在类中的局部位置时,只能访问该局部被final修饰的局部变量
class Demo
{
final int x= 2;
final double
MY_PI = 3.14;
final void show1()
{
}
void show2()
{
}
}
class SubDemo extends Demo
{
void show()
{
}
}
问题:
1、可不可以 final int x; x=2; ? //可以
2、用final修饰的成员不进行初始化,若打印不进行赋值的final成员,编译错误。
class Demo
{
public static void main(String[] args){
//final int x=1; 此方法可以int y = 5;System.out.println(y);final int x;//System.out.println(x);//编译错误,x没有初始化x=3; //可以先不赋值,然后再赋值一次System.out.println(x);
}
}
6、抽象类
/*
当多个类中出现相同功能,但是功能主体不同,这类可以进行向上抽取,这时,只抽取功能定义,而不抽取功能主题,用abstract。抽象方法必须放在抽象类中,因为若抽象方法放在非抽象类中,类的对象对该抽象方法完全没有意义。
抽象方法:abstract 返回值类型 方法名(); 抽象方法没方法主体
特点:
抽象方法一定存在于抽象类中
抽象方法和抽象类都必须被abstract修饰
抽象类不可以用new创建对象,因为调用抽象方法没意义
抽象类中的方法要被使用,必须由子类重写所有的抽象方法后,建立子类对象来使用。
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类(抽象方法只能存在于抽象类中)。如果子类重写了父类所有抽象方法,则子类可以不是抽象的。(一般情况下子类都是非抽象的,因此使用抽象类抽象方法,可以在一定程度上强迫子类重写一些抽象方法,因为子类需要创建对象,而抽象类不能创建对象)
抽象类和一般类:
没有太大不同,该如何描述事物就如何描述事物,只不过该事物中出现了一些看不懂的东西,这些不确定的部分也是该事物的功能,需要明确出来,但是无法定义主题。通过抽象方法类表示。
抽象类比一般类多了个抽象方法
抽象类不可以实例化
抽象类中可以存在非抽象方法。
抽象方法和一般方法:
一般方法可以被子类直接使用,若子类需要可以对父类方法进行重写。
抽象方法只定义返回值类型和方法名,没有方法主题,需要由子类重写使用。
*/
abstract class student
{
abstract void study();//抽象方法必须存在于抽象类中
}
class BaseStudent extends student
{
void study()//对抽象方法进行重写
{
System.out.println("study");
}
}
7、模板方法模式
/*
需求:获取一段程序运行的时间
原理:获取程序开始和结束的时间并相减
获取时间:System.currentTimeMillis();
当代码完成优化后,就可以解决这类问题。
什么是模板方法?在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,由该类的子类去完成。
*/
方式一:
class GetTime
{
public void getTime()
{
long start = System.currentTimeMillis();
for(int i=0;i<1000;i++)
{
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println("毫秒:"+(start-end));
}
}
方式二:
abstract
class GetTime
{
public
final
void getTime()//final,防止该方法被重写
{
long start = System.currentTimeMillis();
runcode();//程序中不确定的部分,将其暴露出去
long end = System.currentTimeMillis();
System.out.println("毫秒:"+(start-end));
}
public
abstract void runcode();//该功能由子类重写去实现
}
class SubTime extends GetTime
{
public void runcode()
{
for(int i=0;i<1000;i++)
{
System.out.println(i);
}
}
}
8、接口
/*
接口:初期理解,可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象方法时,那么该类可以通过接口形式来表示,用interface来定义接口。
格式特点:
接口中常见定义:常量、抽象方法。
接口中的成员都有固定修饰符
常量:public static final
方法:public abstract
记住:接口中的成员都是public的,但是若public static final public abstract不写的话,系统会自动补上。但是为了阅读性,一般都写上。
注意:
类与类之间是继承关系,因为父类中的成员或方法,子类都可以直接使用。但是类与接口之间是实现关系,因为接口中的方法是抽象的,类必须实现接口中的抽象方法。
接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化,否则子类就是一个抽象类。但可以创建接口的引用,例如接口Inter,可以Inter i;但不可以new Inter();
*/
interface Inter
{
public static final
int NUM = 3;//红色部分可以省略,系统会自动补上
public abstract
void show();//红色部分可以省略,系统会自动补上
}
class Test implements Inter
{
public void show(){};
}
class InterTest
{
public static void main(String[] args)
{
Test t = new Test;
System.out.println(t.NUM);//创建子类对象,调用NUM
System.out.println(Test.NUM);//因为NUM是static的,可直接类调用
System.out.println(Inter.NUM);//NUM是static,接口名可直接调用
}
}
接口可以被类多实现,也是对多继承不支持的转换形式,java支持多实现。也就是说,一个类可以实现多个接口。
注意:java对多继承不支持的原因是,多个父类中可能存在同名不同主体的方法,子类在继承后没办法选择该继承哪一个方法。而在接口中,多个接口中的同名方法都必须由子类去实现,接口中方法没有方法体,所以子类可以自己定义方法体,不存在该选择哪个接口方法的问题。
类与类之间是继承,类与接口之间是实现,接口与接口之间是继承关系(
接口之间可以是多继承,一个接口可以继承多个接口(但是,多个接口之间不能存在方法名相同返回值不同的方法,因为子类对象调用时不知如何调用))。
interface Inter
{
public static final int NUM = 3;//红色部分可以省略,系统会自动补上
public abstract void show();//红色部分可以省略,系统会自动补上
}
interface InterA
{
public abstract void showA();//红色部分可以省略,系统会自动补上
}
class Test implements Inter,InterA
{
public void show()
{
System.out.println("对接口Inter中方法的实现");
}
public void showA()
{
System.out.println("对接口InterA中方法的实现");
}
}
class Students
{
}
//子类可以继承父类的同时,实现多个接口
class SubStudents extends Students implements Inter,InterA
{
}
接口特点:
接口是对外暴露的规则
接口是程序的功能扩展(基本功能定义在类中)
接口可以用来多实现
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
接口与接口之间可以有继承关系