Java基础11(接口 static关键字)

目录

一. 接口

1. 接口的定义

2. 接口的实现

3. 接口和类的关系

4. Comparable接口

4. 抽象类和接口的区别

 小结

二. static关键字

1. 静态成员变量

2. static 静态方法

3. static静态代码块

格式:

作用:

执行顺序:

4. 内部类(后面学)

三. 接口拓展

default 和 static



一. 接口

如果一个抽象类没有字段(成员变量),并且所有方法全部都是抽象方法。在这种场景下,就可以把该抽象类定义为interface接口。所谓interface接口,就是比抽象类还要更佳抽象的一种纯抽象的代码结构。因为它连字段(成员变量)都不能存在,只能包含常量、抽象方法、默认方法等。

1. 接口的定义

类--- class        接口--- interface

接口定义语法规则:

修饰符 interface I接口名{
	1.抽象方法:
		public abstrcat 返回值类型 方法名();
		其中public abstrcat可以省略
	2.静态常量:
		public static final 数据类型 常量名=值;
		其中public static final可以省略
}

[注]:

●接口中的所有的修饰符均是public

●常量自带 public static final

double PI = 3.14;//常量 有默认修饰符 变量不可存在

●方法自带 public abstrcat

	void draw();
	void aaa();

●不能有构造方法

//不能有构造方法
	//Interfaces cannot have constructors
	public IShape() {
		
	}

●不能存在普通的方法

	//不能存在普通的方法
	//Abstract methods do not specify a body
	public void doSth() {
		System.out.println("doSth");
	}

 ●常量不能重新赋值

	System.out.println(is1.PI);
//		The final field IShape.PI cannot be assigned
		is1.PI=777;//常量不能重新赋值

2. 接口的实现

当一个具体的class去实现一个interface时,需要使用implements关键字。

接口实现语法规则:

//类实现接口
修饰符 class 类名 implents 接口名{

}

示例:

IShape接口:

public interface IShape {
	double PI = 3.14;//常量 有默认修饰符 变量不可存在
	void draw();
	void aaa();
}

子类:

//实现类必须要实现接口中的所有的抽象方法,除非此类是抽象类
public class Flower implements IShape {

	@Override
	public void draw() {
		System.out.println("❀");
	}

	@Override
	public void aaa() {
		System.out.println("flower --- aaa");
	}

}
//抽象类实现接口 可以不实现抽象方法
abstract class Star implements IShape {

}

[注]:

●接口和抽象类均不能实例化

//Cannot instantiate the type IShape
		IShape is = new IShape();//接口和抽象类均不能实例化

●面向抽象设计

接口 对象名= new 实现类() 
//面向抽象设计
		IShape is1 = new Flower();
		is1.draw();// ❀

3. 接口和类的关系

●类 --- is a
●接口 --- xxx特性


●类和类直接单继承
●类和接口多实现的,多个接口之间用逗号来分割
●接口和接口之间多继承

示例:

接口:

//定义了一系列的接口,表示可以干的事情,具备某种特质

//会飞的
public interface IFlying {
	void fly();
}

//会跑的
interface IRunning {
	void run();

	// jdk1.8接口中可以包含有方法体的方法: default--默认方法,static--方法
	default void test() {
		System.out.println("111");
	}
}

//会游泳的
interface ISwimming {
	void swim();
}

接口之间是多继承关系:

//接口之间是多继承关系
interface Iaaa extends ISwimming, IRunning {
}

父类:

//定义父类
public class Animal {
	protected String name;

	public Animal(String name) {
		this.name = name;
	}

}

先继承后实现:

子类:

//先继承后实现
//继承Animal,拥有其成员变量和方法(非private)
//实现IRunning接口,(具体跑的特性)--重写run方法
public class Cat extends Animal implements IRunning {

	public Cat(String name) {
		super(name);
	}

	@Override
	public void run() {
		System.out.println("猫" + name + "正在用四条腿跑");
	}

	@Override
	public void test() {
		System.out.println("这个是cat的test方法");
	}
}
public class Duck extends Animal implements Iaaa,IFlying{

	public Duck(String name) {
		super(name);
	}

	@Override
	public void swim() {
		System.out.println(name + "鸭子可以游泳");
	}

	@Override
	public void run() {
		System.out.println(name+"鸭子可以跑");		
	}

	@Override
	public void fly() {
		System.out.println(name+"鸭子可以飞");		
	}

}
//1.类和类直接单继承
//2.类和接口多实现的,多个接口之间用逗号来分割
//3.接口和接口之间多继承
public class Frog extends Animal implements Iaaa {

	public Frog(String name) {
		super(name);
	}

	@Override
	public void swim() {
		System.out.println(name + "青蛙正在游泳");
	}

	@Override
	public void run() {
		System.out.println(name + "青蛙正在跑");
	}

}

测试:

public class Demo01 {
	public static void main(String[] args) {
		// 向上转型 -- 面向抽象设计
		// 强调跑的本领 过多的关注于能力 调用者不必过多关注底层的内部细节
		IRunning cat = new Cat("小猫");
		IRunning frog = new Frog("青蛙");
		IRunning duck = new Duck("鸭子");

		cat.run();
		cat.test();
		frog.run();
		frog.test();
		duck.run();

		ISwimming frog1 = new Frog("青蛙1");
		ISwimming duck1 = new Duck("鸭子1");
		frog1.swim();
		duck1.swim();

		// 如果某个对象想要使用其独特的功能 则对其进行向下转型
		if (duck1 instanceof Duck) {
			Duck d1 = (Duck) duck1;
			d1.fly();
			d1.run();
		}
	}
}

运行结果:

4. Comparable接口

Comparable接口用于进行对象之间的比较,主要用于排序方法。

public class Student implements Comparable {
	private String name;
	private int score;

	public Student(String name, int score) {
		super();
		this.name = name;
		this.score = score;
	}

	@Override
	public String toString() {
		return "[name=" + name + ",score=" + score + "]";
	}

//实现Comparable接口的compareTo()方法
	// ==0 不交换
	// >0 如果希望当前对象排在参数后面,返回大于0的
	// <0 如果希望当前对象排在参数前面,返回小于0的
	@Override
	public int compareTo(Object o) {
		if (o instanceof Student) {
			Student s = (Student) o;
			if (this.score == s.score) {
				return 0;
			} else if (this.score > s.score) {
				return -1;
			} else {
				return 1;
			}
		}
		return 0;
	}

}

测试:

public class Demo01 {
	public static void main(String[] args) {
		Student[] students = new Student[] { new Student("zkt1", 77), new Student("zkt2", 88),
				new Student("zkt3", 99) };
		// 给学生数组排序
//		Arrays.sort(students);
		sort(students);
		System.out.println(Arrays.toString(students));

	}

	public static void sort(Comparable[] array) {
		for (int i = 0; i < array.length - 1; i++) {
			for (int j = 0; j < array.length - 1 - i; j++) {
				if (array[j].compareTo(array[j + 1]) > 0) {
					Comparable c1 = array[j];
					array[j] = array[j + 1];
					array[j + 1] = c1;
				}
			}
		}
	}
}

运行结果:

4. 抽象类和接口的区别

abstract class 抽象类

interface接口

定义

使用 abstract class关键字定义抽象类

使用 interface关键字定义接口

继承

只能extends继承一个class类

可以implements多个interface接口
并且接口之间直接允许多重extends继承

字段(成员变量)

可以定义实例字段(成员变量)

不能定义实例字段(成员变量)

常量

使用static final关键字定义常量

无需任何关键字,只能定义常量(默认修饰符 public static final)

抽象方法

可以定义抽象方法

可以定义抽象方法

非抽象方法

可以定义非抽象方法(普通方法)

可以定义default static方法

构造方法

可以有构造方法

不允许有构造方法

访问修饰符

可以使用任意访问修饰符

只能使用public访问修饰符

 小结

●Java的接口(interface)用于定义纯粹的抽象行为(方法)规范。
●一个类只能extends继承自另一个类(单继承)。但是,一个类可以implements实现多个interface接口(多重实现)。
●一个interface可以继承自多个interface(接口之间允许多重继承)。
●一个类实现interface接口时,要求必须实现该接口中所有的抽象方法。
●接口也是一种“高层”的数据类型,可以用于定义“引用”的类型,也适用于"向上转型"和"向下转型"。
●接口不允许实例化。
●接口的所有方法都是抽象方法,接口不能定义实例字段(成员变量)。
●接口可以定义default方法(JDK版本 >= 1.8),default方法可以包含方法体。
●实现Comparable接口的类,该类的对象之间可以进行“比较”,用于“排序”。

二. static关键字

1. 静态成员变量

在一个class类中定义的成员变量,我们称之为实例成员变量(成员变量)。实例成员变量的特点是,每个实例都有独立的成员变量,各个实例的同名成员变量互不影响。除此以外,还有一种成员变量,是使用static关键字修饰的成员变量,称为静态成员变量:static field。

实例成员变量在每个实例中都有自己的一个独立“空间”,但是静态成员变量只有一个共享“空间”,所有实例都会共享该成员变量。

示例:

Person类:

public class Person {
	// 实例成员变量
	private String name;
	private int age;
	// 静态成员变量
	public static String school;

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

测试类:

Person p1 = new Person("zkt1", 21);
		Person p2 = new Person("zk2", 22);
		//静态成员变量访问方式:
		//1.对象名.成员变量名
		//2.类名.静态变量名
		//成员变量被static修饰,此字段从对象级别提升到类级别
		//改类的所有的对象共享改字段的值
		
		p1.school = "清华大学";// 不推荐
		System.out.println(p1.school);
		p2.school = "浙江大学";
		System.out.println(p1.school);
		System.out.println(p2.school);
		System.out.println(Person.school);// 推荐

静态成员变量访问方式:

类名.静态变量名 --- 推荐        
对象名.成员变量名

[注]:

●成员变量被static修饰,此字段从对象级别提升到类级别

●改类的所有的对象共享改字段的值

对于静态成员变量,无论修改哪个实例的静态成员变量,都是访问相同的内存空间:所有实例的静员态成员变量都被修改了,原因是静态成员变量并不属于实例。


内存情况:

class Person {
    public String name;
    public int age;
    
    // 定义静态成员变量number:
    public static int number;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Main {
    public static void main(String[] args) {
        Person ming = new Person("Xiao Ming", 12);
        Person hong = new Person("Xiao Hong", 15);
        
        ming.number = 88;
        System.out.println(hong.number);
        
        hong.number = 99;
        System.out.println(ming.number);
    }
}


●局部变量不能被static修饰

public class Test{
    static int a = 1;
    static int b = 2;
    public static void main(String[] args) {
    	//Unresolved compilation problem: 
    	//Illegal modifier for parameter c; only final is permitted
        static String c = "3";
        System.out.println(a+b+c);
    }
}

2. static 静态方法

static修饰的方法称为静态方法。调用实例方法必须通过一个实例对象,而调用静态方法则不需要实例对象,通过类名就可以调用。

细节:

●如果一个方法被static所修饰,此方法为静态方法,

●静态方法属于class类级别的,而不属于实例对象。因此,静态方法内部,只能访问静态的,不能访问非静态的成员变量,也不能出现this关键字

// 如果一个方法被static所修饰,此方法为静态方法
	// 类名.方法名()推荐    对象名.方法名()不推荐
	public  static void eat() {
		// 不能访问非静态的成员变量,也不能出现this关键字
		// System.out.println(name );
		System.out.println("你好 要吃饭了");
		System.out.println(school);
		sleep();
	}

	public static void sleep() {
		System.out.println("睡觉的办法");
	}

●普通方法可以访问静态方法和非静态方法

// 普通方法可以访问静态方法和非静态方法
	public void doSth() {
		eat();
		getName();
	}

静态方法调用:

类名.方法名()推荐    
对象名.方法名()不推荐
		Person p1 = new Person("zkt1", 21);
//静态方法调用--推荐类名.方法名()
		Person.eat();

3. static静态代码块

在Java类中使用static关键字和{}声明的静态代码块,静态代码块在“类被加载”的时候运行,而且只运行一次,并且优先于各种代码块以及构造函数。如果一个类中有多个静态代码块,会按照书写顺序依次执行。

格式:

public class CodeBlock {
    static{
        System.out.println("静态代码块");
    }
}

作用:

如果有些代码逻辑或对象,需要在项目启动的时候就执行或创建,这时候就需要静态代码块。比如一个项目启动需要加载的很多配置文件或者数据库连接池对象等,我们就可以都放入静态代码块中。


另外,静态代码块中,只允许调用静态方法或静态的成员变量,不允许调用普通方法或普通成员变量。

class CodeBlock {
	// 静态成员变量
	public static int value;
	
	static {
		System.out.println("静态代码块A");
		register(); // 仅允许调用静态方法
		// sayHello(); // 不允许调用普通方法

        // 允许使用静态成员变量(但是,需要在这个静态代码块之前先定义,再使用)
		value += 10; 
	}
    
    // 静态方法
	public static void register(){
		System.out.println("CodeBlock类的静态方法register()");
	}
    
    // 普通方法
	public void sayHello() {
		System.out.println("普通方法");
	}
}

执行顺序:

●静态代码块>构造代码块>构造方法

●先父类再子类,先静态后非静态

●父静态     子静态     父构造    父构造方法     子构造     子构造方法

Fu类:

public class Fu {
	public Fu() {
		System.out.println("这个是父类的无参构造方法");
	}

	{
		System.out.println("这个是父类的代码块1");
	}
	{
		System.out.println("这个是父类的代码块2");
	}
	
	static {
		System.out.println("这个是父类的静态代码块1");
	}
	
	static {
		System.out.println("这个是父类的静态代码块2");
	}
}

Zi类:

public class Zi {
	public Zi() {
		System.out.println("这个是子类的无参构造方法");
	}

	{
		System.out.println("这个是子类的代码块1");
	}
	{
		System.out.println("这个是子类的代码块2");
	}
	
	static {
		System.out.println("这个是子类的静态代码块1");
	}
	
	static {
		System.out.println("这个是子类的静态代码块2");
	}
}

测试:

Fu fu = new Fu();
		System.out.println("===============");
		Fu fu1 = new Fu();
		System.out.println("***************");
		Zi zi = new Zi();
		System.out.println("===============");
		Zi zi1 = new Zi();

运行结果:

●静态代码块随着类的加载而加载,只加载1次
●构造代码块随着对象的创建而调用,对象创建几次,调用几次

4. 内部类(后面学)

三. 接口拓展

default 和 static

在JDK 1.8及其更高版本中,接口中可以定义default 和 static方法。

IAAA接口:

public interface IAAA {
	int MAX = 2147483637;
	int MIN = -2147483639;
	
	//default
	default  void doSth() {
		System.out.println("1.8新出的有方法体的默认方法");
	}
	//static
	public static  void test() {
		System.out.println("1.8新出的有方法体的静态方法");
	}
}
class Aaa implements IAAA{
	
}

接口对常量访问方式:

接口名.静态常量

默认方法访问:

默认方法实现类的对象名.方法名()

静态方法访问:

接口名.方法名()访问接口中的静态方法
Aaa aa = new Aaa();
		// 不推荐
		System.out.println(aa.MAX);
		System.out.println(aa.MIN);

//		推荐对静态常量访问方式:接口名.静态常量
		System.out.println(IAAA.MAX);
		System.out.println(IAAA.MIN);

		// 默认方法实现类的对象名.方法名()
		aa.doSth();
		
		//静态方法访问
//		aa.test();//实现类的对象名.方法名()不能调用
//		Aaa.test();
		IAAA.test();//接口名.方法名()访问接口中的静态方法

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯诺依曼转世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值