final、接口、多态和static
final
- final 是一个修饰符,被他修饰的不能改变,类似c++语言中的const
- 被他修饰的类不能被继承
- 被他修饰的方法不能被重载
- 被他修饰的变量不能改变值,变成了常量。
修饰类格式
final class 类名{
}
修饰方法格式
修饰符 final 返回值类型 方法名(参数列表){
//方法体
}
修饰变量
- 基本类型只能被赋值一次
- 引用类型的地址值只能被赋值一次
- 引用类型成员变量用final如何初始化
public class FinalDemo01 {
public static void main(String[] args) {
final int a = 10;
//a = 3就会报错
//引用类型用final修饰
final User user = new User();
//user = new User();报错
user.setAge(19);//可以调用
}
}
两种方法将final修饰的成员变量初始化
- 定义变量的时候直接赋值。这种构造方法不能写被修饰的变量了
- 定义变量用final修饰,但是不赋值,在构造方法中赋值。必须在每个构造方法中赋值。
方法一
class User{
final String NAME = "张三";//通常用大写的字母表示
private int age;
}//此方法不用再有后续操作
方法二
class User{
final String NAME;//通常用大写的字母表示
private int age;
}
public User(String name,int age){
this.NAME = name;
this.age = age;
}
//注意:如果有多个构造方法,就必须把所有的age全部赋值。
一切父类引用变量都可以指向子类对象,包括接口与实现类,父类和子类
//父类 一个抽象类 封装了动物类的一些抽象方法
public abstract class Animal {
public abstract void eat();
public abstract void sleep();
}
//接口 封装了能看家这个功能
public interface LookHome{
public abstract void lookDoor();
}
//一个狗的类,继承动物,同时拥有干爹(能飞这个接口功能)
public class Dog extends Animal implements LookHome{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("趴着睡");
}
@Override
public void lookDoor() {
System.out.println("狗看门了");
}
}
//定义一个家的类 包括在家吃饭功能和看门的功能
public class Home {
public void eatAtHome(Animal animal){//传入Animai类,但是子类也可以传入。
animal.eat();
animal.sleep();
}
public void lookHome(LookHome lk){//传入一个接口,但是实现类也可以传入。
lk.lookDoor();
}
}
//测试类
public class Test {
public static void main(String[] args) {
Home home = new Home();
home.eatAtHome(new Dog());//虽然是家类的方法中eatAthome传的参数要求是animal类,
//但是一切父类引用都可以传入子类对象,所以不会报错。
Home h2 = new Home();
h2.lookHome(new Dog());//虽然home类中的lookHome方法要求传入一个LookHome接口,
//但dog类是他的干儿子所以不会报错。
}
}
接口
接口用来封装抽象的方法,为其他的类使用。他只能封装常量和共有的抽象方法。他的作用就是为类做一些拓展。
类用来描述一类事物,接口用来描述
定义一个接口:
//定义一个描述动物行为的接口
public interface LiveAble {
public static final int num = 100;//成员常量的定义方法,修饰符必须写上
//前面修饰符不写java会自动补齐
public abstract void eat();//必须是共有的抽象方法,不写abstract和public也会自动补齐
public abstract void sleep();
}
//动物类实现接口
public class Animal implements LiveAble{//关键字 implements
@Override
public void eat() {
System.out.println("吃饭");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
}
- 类实现接口必须要将接口中的所有抽象方法全部实现。
- 定义的方法必须是共有的并且是抽象的。
- 一个类可以实现多个接口,如果多个接口中的方法重名了,实现一个就可以了。
- 类与类是继承关系,类与接口是实现关系,接口和接口是继承关系
- 接口之间的继承是多对多。
接口和抽象类的区别
成员上 抽象类的成员变量可以是变量,接口只能有常量;前者有构造方法,后者没有;前者可以没有抽象方法。后者只能是抽象的(1.8后有了静态和默认方法)
关系上 接口可以多继承,抽象类不能。
理念上 类是描述一类事物的,接口用来封装特定功能。
JDK 1.8接口新特性
接口有了默认方法和静态方法
public interface MyInterface {
public default void method(){//作用就是如果要添加功能的时候就不用重新写一个接口,
//因为重新写完之后实现类都必须全部实现这个抽象方法,默认方法就不用。
System.out.println("我是一个默认方法1");
}
public static void method2(){
System.out.println("我是一个静态方法");
}
}
public interface MyInterface2 {
public default void method(){
System.out.println("我是一个默认方法2");
}
}
public class MyClass implements MyInterface,MyInterface2 {
@Override
public void method(){
System.out.println("重写接口的默认方法");
}
}
public class Test {
public static void main(String[] args) {
MyClass mc = new MyClass();
mc.method();
System.out.println("------------");
MyInterface.method2();//必须写上类名。
}
}
多态
- 理解多态:一个事物的多种形态
- 多态的定义:父类的引用变量 指向子类的对象
- 多态后一切表现都是父类的表现,只有方法调用的是子类重写的方法。
public class Fu {
String name = "父类成员变量";
public void method(){
System.out.println("父类成员方法");
}
}
public class Zi extends Fu{
String name = "子类成员变量";
int age;
public void method2(){
System.out.println("子类成员方法");
}
public void method(){//重写 method方法
System.out.println("子类重写父类的方法");
}
}
public class Test {
public static void main(String[] args) {
Fu zi = new Zi();
System.out.println(zi.name);
zi.method();
// zi.method2();报错只能调用父类的方法
}
}
多态的好处与弊端
- 多态的好处:拓展功能。
- 弊端:不能再调用子类特有的功能。
转型
- 多态就是向上转型
- 向下转型就是强制类型转换
一个有趣的例子说明转型:儿子扮父亲
//父类
public class Father {
public void jiangKe(){
System.out.println("英语");
}
public void diaoYu(){
System.out.println("钓鱼");
}
}
//子类
public class Son extends Father {
//重写父类的方法
public void jiangKe(){
System.out.println("Java");
}
public void playGame(){
System.out.println("玩游戏");
}
}
//测试类
public class Test {
public static void main(String[] args) {
//多态
Father f = new Son();
//运行的重写后的方法
f.jiangKe();
//儿子继承了父亲 有钓鱼功能可以调用
f.diaoYu();
//多态后不能调用子类特有功能
// f.playGame();
//向下转型 儿子卸妆变回自己
Son s = (Son)f;
s.playGame();
}
}
注意点
不能这样:Father f = new Father() Son s = (Son) f会报错。
static修饰符
static修饰符可以修饰类的成员、成员变量、成员方法
被static修饰的成员 不在属于某个对象、属于某个类。被类的所有对象共享。
- 静态成员在方法区中首先把静态的变量和方法放到里面并且赋予初始值!注意,对象在创建的时候才会有初始值,这个先于对象。
- 由于静态成员放在静态区,这个区是一个共享区,改变是实时的。
###对静态成员的访问
类名.变量名;
类名.方法名(实际参数);
当然也可以对象.变量名/方法名。但是不推荐!
注意事项
static修饰的成员随着类的加载而加载 优先于对象存在
静态只能直接访问静态 不能使用this/super
小例子
public class Person {
String name;
static int age;
public static void method(){
System.out.println("我是一个静态方法");
//静态可以直接访问静态
System.out.println(age);
// //静态不能直接访问非静态
// System.out.println(name);
//静态优先对象出现,所以要创建对象后才可以使用对象的东西。
Person p = new Person();
p.name = "Li";
System.out.println(p.name);
}
}