目录
提示:这里介绍static、接口、多态和内部类的知识点;
提示:以下是本篇文章正文内容,下面案例可供参考
一、Static
概述:static是一个关键字,表示静态的意思,用来修饰成员变量,成员方法和代码块;
1、static修饰成员变量:
1、格式:
修饰符 static 数据类型 变量名;
public static int num;
2、访问方式:
1、对象名.静态变量名;
2、类名.静态变量名;---->推荐使用
3、特点:
1、被static修饰的成员变量叫做静态成员变量或者类变量;
2、被static修饰的成员变量会被该类的所有对象所共享;
3、被static修饰的成员变量,如果被某一个对象修改后,
其他所有的对象访问到变量的值都是修改后的值;
2、static修饰成员方法:
1、格式:
修饰符 static 返回值类型 方法名(形参列表){}
public static void method(形参列表){}
2、访问方式:
1、对象名.静态变量名;
2、类名.静态变量名;---->推荐使用
3、静态方法调用的注意事项:
1、静态方法中不能出现this关键字
2、静态方法中只能访问静态成员变量和静态成员方法;
3、静态方法中不能直接访问非静态的成员变量和成员方法;
4、非静态方法中可以直接访问一切的成员变量和成员方法;
3、static修饰代码块:
1、格式:
static{
....
}
2、位置:类中方法外;
3、执行:
1、随着类的加载而执行,并且只会执行一次;
2、类的加载:第一次使用该类的时候,就会加载,并且只会加载一次;
案例:
public class Chinese {
static {
System.out.println("Chinese 静态代码块...");
}
public Chinese(){
System.out.println("Chinese 空参构造...");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("开始");
Chinese c1 = new Chinese();
Chinese c2 = new Chinese();
System.out.println("结束");
}
}
二、接口
1.接口的概述:
概述:接口是Java语言中的一种引用类型,主要用来存储方法的;
1、格式:
修饰符 interface 接口名{}
public interface Fu{}
2、实现接口:
修饰符 class 实现类 implements 接口{}
public class Impl implements Fu{}
3、接口中的成员:
1、常量---->jdk7及其以前出现
2、抽象方法---->jdk7及其以前
3、默认方法---->jdk8
4、静态方法---->jdk8
5、私有方法---->jdk9
4、定义接口需要使用interface关键字,编译后也会产生class文件
5、接口没有构造方法,也不能创建对象,所以一般只供实现类实现的,类似于继承
6、实现接口的类叫做实现类,如果实现类是一个普通类,则必须重写接口中的所有抽象方法,否则实现类是一个抽象类
2、接口中成员的访问特点:
接口中成员的访问特点:
1、接口中常量:只要共接口名直接访问,也可以被实现类继承
2、接口中的抽象方法:就是供实现类重写的
3、接口中的默认方法:可以供实现类对象直接调用,或者被实现类重写
4、接口中的静态方法:只供接口名直接访问,不可以被实现类继承
5、接口中的私有方法:只能在接口内部方法中调用,不可以被实现类继承
案例:
public interface IA{
//常量使用public static final修饰,可以省略
public static final int num = 10;
//抽象方法:使用public abstract修饰,可以省略
public abstract void method1();
//默认方法:使用public default修饰,不可以省略
public default void method2(){
sout("这是IA中的一个默认方法");
}
//静态方法:使用public static修饰,不可以省略
public static void method3(){
sout("这是IA中的一个静态方法...");
}
//私有方法:使用private修饰,不可以省略(私有方法只有在jkd9以上的版本才支持)
private void method4(){
sout("这是IA中的一个私有方法...");
}
}
public class Imp implements IA{
@Override
public void method1(){
sout("这是Imp类中的一个method1方法...");
}
@Override
public void method2(){
sout("这是Imp类中的一个method2方法....");
}
}
public class Test {
public static void main(String[] args) {
// 访问接口中的常量
System.out.println(IA.NUM);// 10
System.out.println(Imp.NUM);// 10
// 访问接口中的抽象方法
Imp imp = new Imp();
imp.method1();
// 访问接口中的默认方法
imp.method2();
// 访问接口中的静态方法
IA.method3();
}
}
三、多态
1、概述:
1、多态是面向对象三大特征之一。
2、多态指对于同一行为,对于不同的对象,具有不同的表现形式。在程序中,表示对同一方法,不同
的对象有不同实现。
3、实现多态的前提条件:
①、继承或者实现
②、父类引用指向子类对象 eg: Fu f = new Zi();
③、方法的重写(没有重写方法多态是没有意义的)
4、格式:
父类的引用指向子类的对象:
格式: 父类类型 变量名 = new 子类类型(实参);
eg: Fu f = new Zi();
接口的引用指向实现类的对象:
格式: 接口名 变量名 = new 实现类名(实参);
eg: IA a = new Imp();
2、多态时访问成员的特点:
1.成员变量: 编译看左边(父类),运行看左边(父类)
2.非静态成员方法:编译看左边(父类),运行看右边(子类)
3.静态成员方法: 编译看左边(父类),运行看左边(父类)
记忆: 除了非静态成员方法编译看左边,运行看右边,其余都看左边
案例:
class Fu{
int num = 10;
public void method1(){
System.out.println("Fu 非静态方法method1...");
}
public static void method2(){
System.out.println("Fu 静态方法method2...");
}
}
class Zi extends Fu{
int num = 20;
public void method1(){
System.out.println("Zi 非静态方法method1...");
}
public static void method2(){
System.out.println("Zi 静态方法method2...");
}
}
public class Test {
public static void main(String[] args) {
// 父类的引用指向子类的对象
Fu f = new Zi();
System.out.println(f.num);// 10
f.method1();// Zi 非静态方法method1...
f.method2();// Fu 静态方法method2...
}
}
3、多态的应用场景:
3.1、变量多态 -----> 意义不大
class Animal{
public void eat(){
System.out.println("吃东西...");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头...");
}
}
class Cat extends Animal{ }
public class Test {
public static void main(String[] args) {
// 父类的引用指向子类的对象
Animal anl1 = new Dog();
// 变量多态
Animal anl2 = new Cat();
// 变量多态
// 使用anl1变量一定要根据多态时成员访问特点去使用
anl1.eat();// 狗吃骨头...
}
}
3.2、形参多态 -----> 常用
概述:参数的类型是父类类型,那么就可以接收该父类类型的对象以及该父类类型的所有子类
对象
class Animal{
public void eat(){
System.out.println("吃东西...");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头...");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼...");
}
}
public class Test {
public static void main(String[] args) {
Dog d = new Dog();
method(d);// 狗吃骨头...
System.out.println("======");
Cat c = new Cat(); method(c);// 猫吃鱼...
}
// 定义一个方法,既可以接收Dog对象也可以接收Cat对象,甚至Animal类对象以及Animal 类其他子类对象,并且在方法中调用eat方法
// 形参多态: 参数的类型是父类类型,那么就可以接收该父类类型的对象以及该父类类型的 所有子类对象
// 实参赋值给形参的时候构成了多态
public static void method(Animal anl){
anl.eat();
}
// 需求:定义一个方法,可以接收Dog对象,并且在方法中调用eat方法
/*public static void method1(Dog dog){ dog.eat(); }*/
// 需求:定义一个方法,可以接收Cat对象,并且在方法中调用eat方法
/*public static void method2(Cat cat){ cat.eat(); }*/ // ...
}
3.3、返回值多态 -----> 常用
结论: 返回值类型为父类类型,那么就可以返回该父类类型的对象,或者该父类类型的子类对象
对象
class Animal {
public void eat() {
System.out.println("吃东西...");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃骨头...");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼...");
}
}
public class Test {
public static void main(String[] args) {
// 接收返回值的时候其实就是多态:
Animal anl1 = new Dog();
Animal anl1 = method1("Dog");
anl1.eat();// 狗吃骨头...
System.out.println("=====");
// 接收返回值的时候其实就是多态:
Animal anl2 = new Cat();
Animal anl2 = method1("Cat");
anl2.eat();// 猫吃鱼...
}
// 定义一个方法,可以返回Dog对象,也可以返回Cat对象,也可以返回Animal对象,或者Animal 类的其他子类对象 // 返回值多态: 返回值类型为父类类型,那么就可以返回该父类类型的对象,或者该父类类型的子 类对象
public static Animal method1(String classType) {
//return new Dog();
//return new Cat();
//return new Animal();
if ("Dog".equals(classType)) {
return new Dog();
} else if ("Cat".equals(classType)) {
return new Cat();
} else if ("Animal".equals(classType)) {
return new Animal();
} else { return null; }
}
}
4、多态的好处和弊端
4.1、好处:
可以将方法的参数定义为父类引用,使程序编写的更简单,提高程序的灵活性,扩展性 案例参考多态的应用场景;
4.2、弊端:
无法直接访问子类独有的成员变量和成员方法(因为多态时成员访问特点编译都是看左边(父 类))
4.3、案例:
class Animal {
public void eat() {
System.out.println("吃东西...");
}
}
class Dog extends Animal {
// 独有的成员变量
int num = 10;
@Override
public void eat() {
System.out.println("狗吃骨头...");
}
// 独有的成员方法
public void lookHome() {
System.out.println("狗正在看家...");
}
}
public class Test {
public static void main(String[] args) {
// 多态的弊端: 无法访问子类独有的成员变量和成员方法
// 变量多态
Animal anl1 = new Dog();
// System.out.println(anl1.num);// 编译报错,因为编译看左边,父类没有 num成员变量
// anl1.lookHome();// 编译报错,因为编译看左边,父类没有lookHome成员方法
// 返回值多态
Animal anl2 = method1("Dog");
// System.out.println(anl2.num);// 编译报错,因为编译看左边,父类没有 num成员变量
// anl2.lookHome();// 编译报错,因为编译看左边,父类没有lookHome成员方法 }
// 形参多态
public static void method(Animal anl) {
anl.eat();
// anl.lookHome();// 编译报错,因为编译看左边,父类没有lookHome成员方法
}
// 返回值多态
public static Animal method1(String classType) {
//return new Dog();
//return new Cat();
//return new Animal();
if ("Dog".equals(classType)) {
return new Dog();
} else if ("Animal".equals(classType)) {
return new Animal();
} else {
return null;
}
}
}
5、引用类型转换
5.1、为什么要转型
1、为了实现多态
2、为了解决多态的弊端
5.2、如何转型:
1、向上转型: 父类类型 变量名 = new 子类名(实参); 向下转型: 子类类型 变量名 = (子类类型) 父类类型的变量;
2、注意:
父类类型的变量指向的对象一定是左边子类类型的对象,否则会报类型转换异常 ClassCastException
5.3、避免转型异常—>转型判断
1、instanceof关键字
2、格式: 变量名 instanceof 数据类型
3、执行:
如果变量指向的对象的数据类型是属于后面的数据类型,就返回true,否则返回false
5.4、案例:
class Animal {
public void eat() {
System.out.println("吃东西...");
}
}
class Dog extends Animal {
// 独有的成员变量
int num = 10;
@Override
public void eat() {
System.out.println("狗吃骨头...");
}
// 独有的成员方法
public void lookHome() {
System.out.println("狗正在看家...");
}
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
}
public class Test1 {
public static void main(String[] args) {
/*
为什么转型
1.为了实现多态
2.为了解决多态的弊端(无法访问子类独有的成员变量和成员方法)
引用类型转换分类
向上转型:
子类类型向父类类型转换的过程,称为向上转型。这个过程是默认的。
格式:
父类类型 变量名 = new 子类类型() 或 子类对象引用;
Dog d = new Dog();
Animal anl = new Dog();
Animal anl = d;
向下转型:
父类类型向子类类型转换的过程,称为向下转型,这个过程需要强制执 行。
格式:
子类类型 变量名 = (子类类型) 父类类型变量;
要求:
父类类型的变量必须指向的是前面子类类型的对象
类型转换判断:
使用instanceof关键字
格式:
变量名 instanceof 数据类型
执行:
如果变量指向的对象是属于后面的数据类型,那就返回true
如果变量指向的对象不属于后面的数据类型,那就返回false */
// 向上转型: 父类类型的引用指向子类类型的对象
Animal anl1 = new Dog();
anl1.eat();
// System.out.println(anl1.num);// 编译报错
// anl1.lookHome();// 编译报错
//Dog d = new Dog();
//Animal anl2 = d;
System.out.println("=======");
// 改变anl1指向的对象
anl1 = new Cat();
// 向下转型: 子类类型向父类类型转换的过程
if (anl1 instanceof Dog){
Dog dog = (Dog) anl1;
System.out.println(dog.num);
dog.lookHome();
}
}
}
四、内部类
1、4.1 内部类的概述
1、概述: 将一个类定义在另一个类的里面,里面的那个类就叫做内部类,外面的那个类就叫做外部类
2、特点:
内部类是一个独立的类,在编译后,有自己独立的class文件,前面冠以:外部类名+$+内部类 类名
3、分类:
成员内部类
匿名内部类
局部内部类(自己了解)
4.2 成员内部类
1、概述: 定义在类的成员位置(类中方法外)的类就叫做成员内部类
2、格式:
class 外部类名{ class 内部类名{ } }
3、成员访问特点:
成员内部类中的成员变量和成员方法在其他类中访问,需要创建成员内部类对象
4、格式: 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
案例:
public class Body {
public class Heart{
// 成员变量
int numN = 20;
// 成员方法
public void methodN1(){
System.out.println("成员内部类的methodN1方法...");
}
}
}
public class Test {
public static void main(String[] args) {
// 创建Heart对象
Body.Heart bh = new Body().new Heart();
System.out.println(bh.numN); bh.methodN1();
}
}
注意事项: 在成员内部类中,可以直接访问外部类的一切成员,包括外部类的私有成员
在外部类中,需要直接访问内部类的成员,需要创建内部类对象来访问
public class Body {
int numW = 10;
public void methodW1(){
System.out.println("外部类的methodW1方法...");
}
// - 在外部类中,需要直接访问内部类的成员,需要创建内部类对象来访问
public void methodW2(){
System.out.println("外部类的methodW2方法...");
// 创建内部类对象
Heart heart = new Heart();
System.out.println(heart.numN);
heart.methodN1();
}
public class Heart{
// 成员变量 int numN = 20;
// 成员方法
public void methodN1(){
System.out.println("成员内部类的methodN1方法...");
}
// - 在成员内部类中,可以直接访问外部类的一切成员,包括外部类的私有成员
public void methodN2(){
System.out.println(numW); methodW1();
}
}
}
public class Test {
public static void main(String[] args) {
// 创建Heart对象
Body.Heart bh = new Body().new Heart();
System.out.println(bh.numN);
bh.methodN1();
bh.methodN2();
System.out.println("======");
new Body().methodW2();
}
}
4.3 匿名内部类(重点)
1、概述
本质其实就是一个类的子类对象
本质其实就是一个接口的实现类对象
2、格式
new 类名(){ 必须重写所有抽象方法 };
new 接口名(){ 必须重写所有抽象方法 };
3、使用场景
如果想得到一个抽象类的子类对象,那么就可以直接给该类的匿名内部类
如果想得到一个接口的实现类对象,那么就可以直接给该接口的匿名内部类
案例1:
abstract class Animal{
public abstract void eat();
}
public class Test {
public static void main(String[] args) {
// 需求:调用Animal类的eat方法
/*
以前:
1.创建一个子类继承Animal类,在子类中重写eat方法
2.创建子类对象
3.使用子类对象调用eat方法
现在:
直接创建Animal类的匿名内部类,然后使用该匿名内部类调用eat方法即可
*/
// 父类的引用指向子类的对象
Animal anl1 = new Animal() {
@Override public void eat() {
System.out.println("匿名内部类的eat...");
}
};
anl1.eat();
}
}
案例2:
interface IA{
void show();
}
public class Test {
public static void main(String[] args) {
// 需求:得到IA接口的实现类对象调用show方法
/*
以前:
1.创建一个实现类实现IA接口,重写show方法
2.创建实现类对象
3.使用实现类对象调用show方法
现在:
直接创建IA接口的匿名内部类调用show方法
*/
IA a = new IA() {
@Override public void show() {
System.out.println("匿名内部类的show");
}
};
a.show();
System.out.println("=====");
new IA() {
@Override public void show() {
System.out.println("匿名内部类的show");
}
}.show();
}
}
java后续基础内容正在快马加鞭更新中,内容若有误,欢迎各位码友提出建设性意见。