static关键字
static关键字可以用来修饰成员变量和成员方法,被修饰的成员时属于类
,而不是单单属于某个对象,也就是说,可以不依赖对象去调用
类变量
当static
修饰成员变量时,该变量就是类变量,该类的每一个对象都共享同一个类变量的值,任何对象都可以更改类变量的值,但是也可以在不创建对象的情况下对类变量进行操作。
格式:
static 数据类型 变量名
应用:static修饰的变量具有记忆功能
静态方法
static 关键字修饰成员方法,我们叫类方法,习惯叫静态方法
修饰符 static 返回值类型 方法名(参数列表){
}
- 静态方法可以直接访问类变量和静态方法
- 静态方法不能直接访问普通成员方法和成员变量,反之,成员方法可以直接访问类变量和静态方法
- 静态方法中不能使用this关键字
静态方法只能访问静态成员
调用格式
被static修饰的成员建议通过类名直接访问
类名.类变量名
类名。静态方法()
演示:
//访问类变量
System.out.println(Student.numberOfStudent);
//调用静态方法
Student.showNum();
静态代码块
静态代码块,定义在成员位置,使用static修饰的代码块{}
- 位置:类中方法外
- 执行:随着类的加载而执行且执行一次,优先于main方法和构造执行
作用,给类变量进行初始化赋值
public class Game {
public static int number;
public static ArrayList<String> list;
//作用,给类变量进行初始化赋值
static {
number = 2;
list = new ArrayList<String>();
list.add("lisi");
}
}
public class TestGame {
public static void main(String[] args) {
System.out.println(Game.number);
System.out.println(Game.list);
}
}
- 总结 static关键字可以修饰变量,方法,代码块。使用的主要目的是我们不想创建对象的情况下去调用方法。
Arrays类
import java.util.Arrays; 其包含的所有方法均为静态方法,调用起来非常简单
- Arrays.toString();返回数组内容的字符串表示形式
- Arrays.sort(arr); 对指定的数组进行升序排序
public static void main(String[] args) {
int[] arr = new int[10];
for (int i = 0; i < 10 ; i++) {
arr[i] = new Random().nextInt(100);
}
System.out.println("排序前" + Arrays.toString(arr));
// 升序排序
Arrays.sort(arr);
System.out.println("排序后" + Arrays.toString(arr));
}
Math类
Math类包含常用的基本数学运算方法,其包含的所有方法均为静态方法,调用起来非常简单
方法介绍:
public static void main(String[] args) {
double d1 = Math.abs(-5); // 绝对值
System.out.println(d1);
double d2 = Math.ceil(-3.3); //返回大于等于参数的最小整数
System.out.println(d2);
double d3 = Math.floor(-3.3);
System.out.println(d3); // 返回小于等于参数的最小整数
double d4 = Math.round(5.5); // 四舍五入
System.out.println(d4);
}
多态
多态是继承,封装之后面向对象的三大特征一直。
同一种行为,具有不同的表现形式
前提
- 1.继承或者实现【二选一】
- 2.方法的重写【意义体现:不重写无意义】
- 3.父类引用指向子类对象【格式体现】
体现
体现的格式
父类类型 变量名 = new 子类对象;
变量名.方法名
父类类型:指子类对象继承的父类类型,或者实现的父接口类型
Fu f = new Zi();
f.method();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误,如果有,执行的时子类重写后的方法
演示:
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal {
@Override
public void eat(){
System.out.println("狗吃骨头");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
多态的好处
在实际的开发过程中,父类类型作为方法的形式参数,传递子类对象给方法,进行方法的调用,更能体现多态的扩展性与遍历性。
由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当然可以把Cat对象和Dog对象传递给方法。
当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果showCatEat和showDogEat方法一致。
不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXXXeat方法,直接使用showAnimalEat都可以完成。
所以,堕胎的好处使程序编写简单,并有良好的扩展性。
引用类型转换
向上转型
- 向上转型:当父类引用指向子类对象时。
父类类型 变量名 = new 子类对象;
向下转型
父类类型向子类类型向下转化的过程,强制的
子类类型 变量名 = (子类类型) 父类变量名()
为什么转型
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误,也就是说,不能调用子类拥有而父类没有的方法。编译都错误,更别说运行了,所以,想要调用子类特有的方法,必须向下转型。
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("小猫吃鱼");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void watchHouse(){
System.out.println("看家");
}
}
public static void main(String[] args) {
Animal a = new Cat(); // 向上转型
a.eat();
// 为了避免转型发生异常,最好先做个判断
// 变量名 instanceof 数据类型
// 向下转型
if(a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse();
}else if (a instanceof Dog){
Dog d = (Dog)a;
d.watchHouse();
}
}
接口(interface)
是Java中一种引用类型,是方法集合,如果类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法。
- 包含抽象方法(JDK7以前)
- 默认方法和静态方法(JDK8)
- 私有方法(JDK9)
接口也会被编译成.class
文件,但是接口不是类。
使用接口,不能创建对象,但是可以被实现(implements),类似继承,一个实现接口的类,同样需要实现接口的所有抽象方法,否则它必须是一个抽象类。
定义格式
public interface 接口名{
//抽象方法
//默认方法
//静态方法
//私有方法
}
含有抽象方法
public interface InterFaceDemo {
public abstract void method();
}
可以省略abstract
public interface InterFaceDemo {
public void method();
}
含有默认方法和静态方法
- 默认方法:使用
default
修饰,不可以省略,供子类调用或者子类重写 - 静态方法:使用
static
修饰,供接口直接调用
public interface InterFaceDemo {
public default void method(){
//执行语句
}
public static void method2(){
//执行语句
}
}
含有私有方法和私有静态方法
供接口中的默认方法或者静态方法调用
public interface InterFaceDemo {
private void method(){
// 执行语句
}
}
基本实现
类与接口的关系为实现关系,即类实现接口,该类叫做实现类,也可以被称为接口的子类。
非抽象子类实现接口:
1.必须重写接口中所有的抽象方法
2.继承了接口的默认方法,可以直接调用,也可以重写
注:接口的默认方法是抽象方法 ,所以定义抽象方法可以省略abstract
class 类名 implements 接口名{
//重写接口中所有的抽象方法
//重写接口中的默认方法
}
抽象方法的使用
public interface LiveAble {
// 定义抽象方法
public abstract void eat();
public abstract void sleep();
}
实现类
public class Animal implements LiveAble {
@Override
public void eat() {
System.out.println("就知道吃");
}
@Override
public void sleep() {
System.out.println("还睡呀");
}
}
测试
public class TestInterface {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
a.sleep();
}
}
默认方法
public default void fly(){
System.out.println("飞飞飞");
}
重写默认方法
public class Animal implements LiveAble {
@Override
public void eat() {
System.out.println("就知道吃");
}
@Override
public void sleep() {
System.out.println("还睡呀");
}
@Override
public void fly() {
System.out.println("左右飞");
}
}
测试
public class TestInterface {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
a.sleep();
a.fly(); // 调用默认方法
}
}
静态方法
public static void run(){
System.out.println("嗷嗷跑");
}
public class Animal implements LiveAble {
// 无法重写静态方法
}
测试
public class TestInterface {
public static void main(String[] args) {
LiveAble.run();
}
}
私有方法
- 私有方法:只有默认方法可以调用
- 私有静态:默认方法和静态方法可以调用
存在的意义:当接口中存在多个默认方法,并且方法中有重复的内容,可以抽取成一个私有方法,供默认方法调用
public default void fly(){
System.out.println("飞飞飞");
func1();
func2();
}
private void func1(){
System.out.println("func1");
}
private void func2(){
System.out.println("func2");
}
接口的多实现
一个类只能继承一个类,但是可以实现多个接口
一个类可以继承一个父类,同时实现多个接口
class 类名 [extends 类名] implements 接口1,接口2,接口3...{
}
抽象方法
接口中有多个抽象方法,实现类必须重写所有抽象方法,如果抽象方法有重名的,只需要重写一次
。
默认方法
接口中有多个默认方法时
,实现类都可以继承使用,如果默认方法有重名的,必须重写一次
静态方法
接口中存在同名的静态方法并不会冲突,因为使用接口名调用
优先级
当一个类,既继承了一个父类,又实现了多个接口时,父类中的成员方法和接口中的默认方法重名,子类就近选择执行父类的成员方法。
接口的多继承
一个接口可以继承多个接口,使用extends,如果有重名的,子接口只需要重写一次即可
总结
- 接口中,无法定义成员变量,但是可以定义常量,其值不可改变,默认使用
public static final 修饰 - 接口中,没有构造方法,不能创建对象
- 接口中,没有静态代码块
电脑模拟案例
分析
- USB接口,包含开启、关闭
- 笔记本类,包含运行、关机、使用USB
- 鼠标类,实现USB接口,具备点击功能
- 键盘类,实现USB接口,具备敲击功能
实现
接口