final关键字
final关键字是最终的意思,可以修饰(方法,变量,类)
final修饰的特点
修饰方法:表明该方法是最终方法,不能被重写
修饰变量:表明该变量是常量,不能再次被赋值
修饰类:表明该类是最终类,不能被继承
/变量在栈中存
/new出来的东西在堆中存
基本数据类型变量:其值不能被更改
//常量的命名规范:如果是一个单词,所有字母大写,如果是多个单词,所有字母大写
//但中间需要使用_分隔
final int NAX = 10;
final int MAX_VALUE = 20;
引用数据类型变量:内存地址不能被更改,但是可以修改对象的属性值
final Student stu = new Student();
stu.setName("张三");
stu.setName("李四");
//final修饰成员变量 初始化时机
//1.在创建的时候,直接给值
//2.在构造方法结束之前,完成赋值
代码块:
{}括起来的代码被称为代码块
局部代码块:
位置:方法中定义的
作用:限定变量的生命周期,及早释放,提高内存利用率
构造代码块:
位置:类中方法外
特点:每次构造方法执行时,都会执行该代码块,并且在构造方法执行前执行
作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
静态代码块:
位置:类中方法外
特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
作用:在类加载的时候做一些数据初始化的操作 一般用于安装驱动
接口:
多实现
一个类中,所有的方法,都是抽象方法的时候,我们可以将其定义为接口
接口也是一种引用数据类型,它比抽象类还要抽象
接口存在的两个重要意义
1.规则的定义
2.程序的扩展
接口的定义和特点:
接口用关键字interface来定义
public Interface 接口名{}
接口不能实例化
接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名{}
接口的子类 (实现类)
要么重写接口中的所有抽象方法
要么是抽象类
例子:
public class Demo1 {
public static void main(String[] args) {
Cat c = new Cat();
c.catchMouse();
Dog d = new Dog();
d.catchMouse();
}
}
interface CM{
public abstract void catchMouse();//抽象方法
}
class Cat implements CM{
//接口实现
@Override
public void catchMouse() {
//重写方法
System.out.println("猫抓老鼠");
}
}
class Dog implements CM{
//接口实现
@Override
public void catchMouse() {
//重写方法
System.out.println("狗拿耗子");
}
}
注意:接口和类的实现关系,可以单实现,也可以多实现.
public class 类名 implements 接口1,接口2{}
public class Test1Interface {
/*
接口定义格式:
public interface 接口名{}
类实现接口的格式:
public class 类名 implements 接口名{}
*/
public static void main(String[] args) {
//Inter i = new Inter();接口不允许创建对象
InterImpl ii = new InterImpl();
ii.study();
}
}
public class InterImpl implements Inter,InterA{
@Override
public void study() {
System.out.println("我是实现类中的study方法");
}
@Override
public void print1() {
}
@Override
public void print2() {
}
}
public interface Inter {
public abstract void study();
}
public interface InterA {
public abstract void print1();
public abstract void print2();
}
接口中成员的特点:
成员变量:
接口中成员变量只能是常量
系统会默认加入三个关键字:public static final
构造方法:
接口中没有
成员方法:
成员方法:只能是抽象方法,系统会默认给两个关键字
public abstract
public class TestInterface {
/*
接口中成员变量只能是常量,系统会默认加入三个关键字
public static final
构造方法:接口中没有
成员方法:只能是抽象方法,系统会默认给两个关键字
public abstract
*/
public static void main(String[] args) {
System.out.println(Inter.NUM);
}
}
class InterImpl extends Object implements Inter{
//所有的类默认的父类是Object
public InterImpl(){
super();
}
public void method(){
//num = 20;
System.out.println(NUM);
}
@Override
public void show() {
}
}
interface Inter {
//接口中的变量是常量,默认会被final,static,public关键字修饰
public static final int NUM = 10;
//public Inter(){}
public abstract void show();
}
JDK8版本中接口成员的特点:
JDK8版本后:
1.允许在接口中定义非抽象方法,但是需要使用关键字default修饰,这些方法是默认方法
作用:解决接口升级的问题
2.接口中允许定义static静态方法
接口中默认方法的定义格式:
格式:public default 返回值类型方法名(参数列表){}
范例:public default void show() {}
接口中默认方法的注意事项:
默认方法不是抽象方法,所以不强制被重写.但是可以被重写,重写的时候去掉default关键字
public可以省略,default不能省略
如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写
接口中静态方法的注意事项:
1.静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
2.public可以省略,static不能省略
类和接口的关系:
类和类的关系:
继承关系,只能单继承,但是可以多层继承
类和接口的关系:
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同事实现多个接口
//如果父类和接口出现相同的方法声明,父类的
接口和接口的关系:
继承关系,可以单继承,也可以多继承
多态:
传参数传父类
父类引用指向子类对象
同一个对象,在不同时刻表现出来的不同形态
举例:猫
我们可以说猫是猫:猫 cat = new 猫();
我们也可以说猫是动物:动物 animal = new 猫();
这里的猫在不同时刻表现出来了不同的形态,这就是多态
多态的前提和体现:
有继承/实现关系
有方法重写
有父类引用指向子类对象
例子:
public class Test1Polymorphic {
/*
多态的前提:
1.要有(继承\实现)关系
2.要有方法重写
3.要有父类引用,指向子类对象
*/
public static void main(String[] args) {
//当前事物是一只猫
Cat c = new Cat();
//当前事物是一只动物
Animal a = new Cat();
a.eat();
}
}
class Animal{
public void eat(){
System.out.println("动物吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
多态中成员访问的特点:
构造方法:同继承一样,子类会通过super访问父类构造方法
成员变量:编译看左边(父类),执行看左边(父类)
成员方法:编译看左边(父类),执行看右边(父类)
public class Test2Polymorphic {
/*
多态成员访问特点:
成员变量:编译看左边(父类),执行看左边(父类)
成员方法:编译看左边(父类),执行看右边(父类)
*/
public static void main(String[] args) {
Fu f =new Zi();
System.out.println(f.num);//10,但必须有父类中的num
f.method();//Zi...method 父类中必须有method()方法
}
}
class Fu{
int num =10;
public void method(){
System.out.println("Fu...method");
}
}
class Zi extends Fu{
int num = 20;
public void method(){
System.out.println("Zi...method");
}
}
为什么成员变量和成员方法的访问不一样呢?
1.因为成员方法有重写,而成员变量没有
多态的好处和弊端:
好处:提高代码的扩展性
具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接受这父类的任意子对象
弊端:不能调用子类特有的功能
例子:
public class Test3Polymorphic {
public static void main(String[] args) {
useAnimal(new Dog());
useAnimal(new Cat());
}
public static void useAnimal(Animal a){
a.eat();
}
}
abstract class Animal{
public abstract void eat();
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
多态中的转型:
向上转型:从子到父
父类引用指向子类对象
向下转型:从父到子
父类引用转为子类对象
例子:
public class Test4Polymorpic {
public static void main(String[] args) {
//1.向上转型:从子到父
// 父类引用指向子类对象
Fu f = new Zi();
f.show();
//多态的弊端 不能调用子类特有的功能
//f.method();
//A.直接创建子类对象
//B.向下转型
//2.向下转型:从父到子
// 父类引用转为子类对象 强制转换
Zi z = (Zi)f;
z.method();
}
}
class Fu{
public void show(){
System.out.println("Fu...show");
}
}
class Zi extends Fu {
@Override
public void show()
{
System.out.println("Zi...show");
}
public void method() {
System.out.println("我是子类特有的方法,method");
}
}
多态中的转型存在的风险
如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,name在转换的时候就会出现ClassCastException
避免强转出现的问题
关键字:instanceof
使用格式:
变量名 instanceof 类型
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
例子:
public class Test3Polymorphic {
public static void main(String[] args) {
useAnimal(new Dog());
useAnimal(new Cat());
}
public static void useAnimal(Animal a){
a.eat();
if(a instanceof Dog){
Dog dog = (Dog) a;
dog.watchHome();//ClassCastException类型转换异常
}
// Dog dog = (Dog) a;
// dog.watchHome();//ClassCastException类型转换异常
}
}
abstract class Animal{
public abstract void eat();
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃肉");
}
public void watchHome() {
System.out.println("看门");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}