1、static
2、面向对象三大特征 封装、继承、多态
3、final
4、抽象类 接口
5、内部类
static
可以修饰属性也可以是行为。
修饰属性的是静态成员变量也叫类变量,修饰行为的是类方法也叫静态方法;属于类,天生就有
不被修饰的属性和行为分别叫做成员变量也叫实例变量和成员方法也叫实例方法;属于每个对象,创建才有
static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。
封装:标准的javabean
继承
子类不能继承父类的构造方法。值得注意的是子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已,可以通过getter/setter方法访问父类的private成员变量。
方法重写:子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。
- 方法重写是发生在子父类之间的关系。
- 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
- 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
子类构造方法执行的时候,都会在第一行默认先调用父类无参数构造方法一次。
子类构造方法的第一行都隐含了一个super()去调用父类无参数构造方法,super()可以省略不写。
class student extends xx{
public Student() {
//super(); // 调用父类无参构造方法,默认就存在,可以不写,必须再第一行
System.out.println("子类无参");
}
//其他省略
}
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的
super()。super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。super(…)是根据参数去确定调用父类哪个构造方法的。
private的成员变量和成员方法可以继承过来,但是不可以调用。只能单继承
多态 (接口,类)
调用成员变量时:编译看左边,运行看左边;成员变量不能更改
调用成员方法时:编译看左边,运行看右边;
//以上调用必须是父类里有这些东西才可以执行,如果是子类特殊的方法或者成员变量就不行了。
Fu f = new Zi();
//编译看左边的父类中有没有name这个属性,没有就报错
//在实际运行的时候,把父类name属性的值打印出来
System.out.println(f.name);
//编译看左边的父类中有没有show这个方法,没有就报错
//在实际运行的时候,运行的是子类中的show方法
f.show();
instance of
此时这个关键字就发挥作用了
语法:变量名 instanceof 数据类型
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false。
final 关键字
final: 不可改变,最终的含义。可以用于修饰类、方法和变量。
类:被修饰的类,不能被继承。
方法:被修饰的方法,不能被重写。
变量:被修饰的变量,有且仅能被赋值一次。
抽象类
- 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意
义。 - 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。 - 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊
的类结构设计。 - 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通
过而报错。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的
方法,没有意义。 - 抽象类存在的意义是为了被子类继承。
理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方
法,交给具体的子类去实现。
接口
接口中的抽象方法默认会自动加上public abstract修饰程序员无需自己手写!!
在接口中定义的成员变量默认会加上: public static final修饰。
-
当两个接口中存在相同抽象方法的时候,该怎么办?
只要重写一次即可。此时重写的方法,既表示重写1接口的,也表示重写2接口的。 -
实现类能不能继承A类的时候,同时实现其他接口呢?
继承的父类,就好比是亲爸爸一样
实现的接口,就好比是干爹一样
可以继承一个类的同时,再实现多个接口,只不过,要把接口里面所有的抽象方法,全部实现。 -
实现类能不能继承一个抽象类的时候,同时实现其他接口呢?
实现类可以继承一个抽象类的同时,再实现其他多个接口,只不过要把里面所有的抽象方法全部重
写。 -
实现类Zi,实现了一个接口,还继承了一个Fu类。假设在接口中有一个方法,父类中也有一个相同
的方法。子类如何操作呢?
处理办法一:如果父类中的方法体,能满足当前业务的需求,在子类中可以不用重写。
处理办法二:如果父类中的方法体,不能满足当前业务的需求,需要在子类中重写。 -
如果一个接口中,有10个抽象方法,但是我在实现类中,只需要用其中一个,该怎么办
可以在接口跟实现类中间,新建一个中间类(适配器类)
让这个适配器类去实现接口,对接口里面的所有的方法做空重写。
让子类继承这个适配器类,想要用到哪个方法,就重写哪个方法。
因为中间类没有什么实际的意义,所以一般会把中间类定义为抽象的,不让外界创建对象
内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。可以把内部类理解成
寄生,外部类理解成宿主。
- 成员内部内,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
- 静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
- 局部内部类,类定义在方法内
- 匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。
成员内部类
外部类.内部类 变量 = new 外部类().new 内部类();
public class Test {
public static void main(String[] args) {
// 宿主:外部类对象。
// Outer out = new Outer();
// 创建内部类对象。
Outer.Inner oi = new Outer().new Inner();
oi.method();
}
}
class Outer {
// 成员内部类,属于外部类对象的。
// 拓展:成员内部类不能定义静态成员。
public class Inner{
// 这里面的东西与类是完全一样的。
public void method(){
System.out.println("内部类中的方法被调用了");
}
}
}
方式二:
public class Outer {
String name;
private class Inner{
static int a = 10;
}
public Inner getInstance(){
return new Inner();
}
}
public class Test {
public static void main(String[] args) {
Outer o = new Outer();
System.out.println(o.getInstance());
}
}
2、静态内部类
外部类.内部类 变量 = new 外部类.内部类构造器;
调用非静态方法的格式:先创建对象,用对象调用
调用静态方法的格式:外部类名.内部类名.方法名();
/ 外部类:Outer01
class Outer01{
private static String sc_name = "黑马程序";
// 内部类: Inner01
public static class Inner01{
// 这里面的东西与类是完全一样的。
private String name;
public Inner01(String name) {
this.name = name;
}
public void showName(){
System.out.println(this.name);
// 拓展:静态内部类可以直接访问外部类的静态成员。
System.out.println(sc_name);
}
}
}
public class InnerClassDemo01 {
public static void main(String[] args) {
// 创建静态内部类对象。
// 外部类.内部类 变量 = new 外部类.内部类构造器; //成员内部类比上面少了一个new
Outer01.Inner01 in = new Outer01.Inner01("张三");
in.showName();
}
}
3、局部内部类
class 外部类名 {
数据类型 变量名;
修饰符 返回值类型 方法名(参数列表) {
// …
class 内部类 {
// 成员变量
// 成员方法
}
}
}
4、匿名内部类
是内部类的简化写法。他是一个隐含了名字的内部类。开发中,最常用到的内部类就是匿名内部类了。
前提:
匿名内部类必须继承一个父类或者实现一个父接口。
interface Swim {
public abstract void swimming();
}
public class Demo07 {
public static void main(String[] args) {
// 使用匿名内部类
new Swim() {
@Override
public void swimming() {
System.out.println("自由泳...");
}
}.swimming();
Swim s2 = new Swim() {
@Override
public void swimming() {
System.out.println("蛙泳...");
}
};
s2.swimming();
}
}
//运行结果:
自由泳...
蛙泳...
使用场景
interface Swim {
public abstract void swimming();
}
public class Demo07 {
public static void main(String[] args) {
// 匿名内部类使用场景:作为方法参数传递
Swim s3 = new Swim() {
@Override
public void swimming() {
System.out.println("蝶泳...");
}
};
// 传入匿名内部类
goSwimming(s3);
// 完美方案: 一步到位
goSwimming(new Swim() {
public void swimming() {
System.out.println("大学生, 蛙泳...");
}
});
goSwimming(new Swim() {
public void swimming() {
System.out.println("小学生, 自由泳...");
}
});
}
// 定义一个方法,模拟请一些人去游泳
public static void goSwimming(Swim s) {
s.swimming();
}
}
//运行结果:
蝶泳...
大学生, 蛙泳...
小学生, 自由泳...