static关键字
静态方法的介绍及基本使用
如果一个成员变量使用static修饰,这个成员变量就不再属于对象了,就属于类,会被该类的所有对象所共享。
被static修饰的成员,可以通过对象调用,也可以通过类名调用(推荐类名调用)
小结:
如果成员变量不使用static修饰,那么这个成员变量属于对象的,要有对象才能调用。
如果成员变量使用static修饰,那么这个成员变量属于类,可以通过类名调用.
静态方法的使用
static修饰的方法。
如果一个方法使用static修饰了,那么这个方法属于类了,不属于对象,会被该类的所有对象共享。
静态方法和非静态方法的使用:
被static修饰的方法,可以通过对象调用,也可以通过类名调用,推荐类名调用。
没有被static修饰的方法,必须有对象才能调用。
调用同一个类中的静态方法,可以省略类名
注意事项
1. 静态不能直接访问非静态。
静态属于类,非静态属于对象,有类的时候还没有对象呢,所以静态不能直接访问非静态。
2. 静态方法不能出现this和super
接口
接口是一个规范(给类定义的规范, 类和接口发生关系后, 类要重写接口中的所有的抽象方法)
接口是一种引用数据类型。
接口的定义格式:
public interface 接口名 {
}
接口编译之后也会生成.class的文件。
接口中可以有以下内容
在JDK7以及之前版本
1. 抽象方法(最核心)
2. 常量
在JDK8的时候
3. 默认方法
4. 静态方法
接口中最核心的内容是抽象方法。
接口中抽象方法的定义和使用
接口中最核心的内容是抽象方法。
在任何版本的JAVA中,接口中都可以有抽象方法。
抽象方法的定义格式:
public abstract 返回值类型 方法名(参数);
注意:
1. 接口中的抽象方法可以省略public abstract关键字。
2. 如果接口中的抽象方法省略public abstract关键字,那么方法也是用public abstract修饰的。
接口中抽象方法的使用:
1. 接口不能创建对象。
2. 我们要定义一个类,使用这个类【实现】接口
3. 这个类要重写接口中的所有的抽象方法。
4. 创建这个类的对象,通过这个对象调用方法。
类实现接口的格式:
public class A implements I {
}
上面代码表示A类实现了I接口。 A类也叫作I接口的实现类。
注意:
一个普通类实现接口时,必须重写这个接口中所有的抽象方法。
一个抽象类实现接口时,可以不重写接口中的抽象方法。
接口中的默认方法的定义和使用
在JDK8的时候,接口中可以有默认方法了。
默认方法定义格式:
public default 返回值类型 方法名(参数) {
方法体;
return 返回值;
}
注意:
1. 默认方法有方法体.
2. 默认方法中public关键字可以省略,如果省略该关键字,那么方法也是用public修饰的。
默认方法的使用:
1. 实现类在实现接口时可以不重写接口中的默认方法,我们可以通过实现类对象直接调用接口中的默认方法。
2. 如果接口中的默认方法不能满足实现类的需要,实现类也可以对默认方法进行重写。 实现类重写接口中的默认方法时,要去掉default关键字。
接口中静态方法的定义使用
在JDK8的时候,接口中可以有静态方法。
静态方法的定义格式:
public static 返回值类型 方法名(参数) {
方法体;
return 返回值;
}
注意:
1. 静态方法中public可以省略。
2. 如果省略public,那么该方法也是用public修饰的。
静态方法的使用:
接口中的静态方法要通过接口名字直接调用。
接口中定义的静态方法不能通过实现类去调用。
接口中常量
接口中可以有成员变量,从效果上看,这个成员变量就是常量。
在任何版本的JAVA中,接口中都可以有常量。
常量的定义格式:
public static final 数据类型 常量名 = 值;
因为使用final修饰了,所以值不能改变,所以我们把它叫做常量。
注意:
1. 接口常量中的public static final关键字可以省略
2. 如果省略public static final,接口中的常量也是用这几个关键字修饰的。
3. 接口中的常量因为使用static关键字修饰了,所以可以通过接口名直接调用。
4. 接口中的常量不能被改值。
5. 接口中的常量一定要给出默认值
6. 在给接口中的常量命名时,建议所有字母都大写,多个单词之间使用下划线隔开。
一个类实现多个接口
类与类之间的关系是继承, 一个类只能继承一个类
类与接口之间的关系是实现, 一个类可以实现多个接口
接口和接口之间关系是继承, 一个接口可以继承多个接口
继承:extends
实现:implements
类实现多个接口的格式:
public class A implements I1, I2 {
....
}
上面代码表示A类同时实现了I1和I2这两个接口。
注意(了解):
1. 如果多个父接口中有同名的抽象方法,那么对实现类没有影响,实现类只需要正常的对方法进行重写。重写之后的内容是什么,将来执行的内容就是什么
2. 如果多个父接口中有同名的默认方法,会产生冲突,实现类必须要对默认方法进行重写。
一个类继承父类同时实现多个接口
一个类继承父类的同时实现多个接口
格式:
public class A extends B implements I1, I2 {
}
上面代码表示A类继承B类同时,实现了I1和I2接口
注意(了解)
如果接口中的默认方法和父类中的方法一样,不会产生冲突,如果通过子类调用方法,用的是父类的。
接口的多继承
接口继承多个接口
格式:
public interface I extends A, B {
..
}
I接口同时继承了,A和B这两个接口。
多态
多态在代码中的体现
多态: 一个事物具备多种形态。
比如小明是一个学生,同时也是一个人,所以小明同时具备学生和人的形态,这个就是多态。
多态的代码体现(父类类型(变量,引用)指向子类对象):
父类类型 变量名 = new 子类类型();
为什么父类类型可以指向子类对象:狗肯定是动物,所以可以把狗当成动物去看待,可以把狗赋值给动物类型。
注意:如果使用多态的方式创建对象,调用方法运行的是子类的方法(创建的是谁的对象,调用的就是谁的方法)
根据多态性,我们可以把子类类型当成父类类型去看待。(可以把狗当成动物去看待。)
好处:
多态的好处:
方法参数如果是父类类型,那么可以传递任何子类对象。
原因:
根据多态性,子类类型可以当成父类类型去看待。 比如狗可以当成动物去看待,因为狗肯定是动物。
所以参数如果需要动物类型(父类),那么我们可以狗对象(子类)
多态访问成员的特点:
/*
多态调用成员变量的特点【了解,不用】
编译看左边父类,如果父类中没有改方法,那么编译时期会报错。
运行看左边父类,真正使用的是父类的变量。
多态调用成员方法的特点。
编译看左边父类,如果父类中没有该方法,那么编译时期会报错。
运行看右边子类,真正运行的是子类的方法。
多态的优缺点:
优点:可以让程序更加灵活。
缺点:只能调用父类里面有的方法,不能调用子类特有的内容。
*/
多态转型
引用类型的转换
向上转型:子类类型转成父类类型
父类类型 变量名 = new 子类类型();
向下转型:父类类型转成子类类型
子类类型 变量名 = (子类类型) 父类变量名;
注意:向下转型之前必须要有向上转型。
如果父类变量表示的对象不是要向下转型的目标类型,向下转型时会报错。(Animal类型的a表示的是Dog对象,但是却把a转成Cat)
多态的弊端,只能调用父类里面有的,不能调用子类特有的功能。
如果想要调用子类特有的方法,那么可以使用向下转型。
instanceof关键字:
instanceof关键字
作用:可以判断某个变量表示的是否是该类型的对象。
格式:
变量名 instanceof 数据类型
举例
a instanceof Dog
判断a是否是Dog类型的对象
使用场景:
在向下转型之前使用instanceof关键字进行判断, 如果父类类型的变量表示的是要强转的子类对象,那么再向下转型。
内部类
成员内部类的定义和使用
如果将一个类定义在另一个类的里面,那么这个就是内部类。
里面的类叫做内部类,外面类叫做外部类。
如果将一个类定义在另一个类的成员位置(类中方法外),那么这个类就是成员内部类。
成员内部类的格式:
public class 外部类 {
public class 内部类 {
//内部类的成员
}
}
注意:
1. 内部类编译后也会生成.class文件。 格式为: 外部类$内部类.class
2. 内部类可以访问外部类的成员。
3. 外部类不能访问内部类中的成员
匿名内部类
匿名内部类。
匿名内部类是一种内部类,只不过这个内部类没有名字。
匿名内部类的作用:临时定义某个类的子类,创建该子类的对象。
匿名内部类的格式:
new 父类或接口() {
重写的方法
}
举例:
new Person() {
重写的方法
}
上面代码真正创建的是Person的子类对象,只不过这个子类叫什么,我们不知道,因为他是匿名的。
接口实现匿名内部类【掌握】
/*
使用接口实现匿名内部类
格式:
new 父类或接口() {
重写的方法
}
*/
public class Demo02Test {
public static void main(String[] args) {
Flyable f = new Flyable() {
@Override
public void fly() {
System.out.println("我不知道我是啥,反正我能飞");
}
};
f.fly();
}
}
匿名内部类当做方法参数传递【掌握】
/*
匿名内部类当做方法参数传递。
*/
public class Demo03Test {
public static void main(String[] args) {
//method(new Dog());
//method方法参数是Animal类型,所以我们可以传递Animal子类对象。
//我们可以向method方法参数位置传递一个匿名内部类对象。
method(new Animal() {
public void eat() {
System.out.println("匿名内部类对象在吃");
}
});
}
/*
定义一个方法,可以让任何动物去吃
*/
public static void method(Animal a) {
a.eat();
}
}