第一篇文章的连接: (超详细笔记整理)动力节点_老杜 | JavaSE零基础 :P329(方法) - P479.
final修饰的方法无法覆盖
final修饰的类无法继承
package Final; /* final 1. final是Java语言中的关键字 2. final表示最终的,不可变的 3. final可以修饰变量以及方法还有类等 4. final修饰的变量 final修饰的局部变量无法重新赋值,final修饰的变量只能赋一次值 5. final修饰的方法 final修饰的方法无法覆盖 6. final修饰的类 final修饰的类无法继承 */ public class Test01 { public static void main(String[] args){ //局部变量 int i = 100; i = 200; /* final int k = 100; k = 0; */ } } //继承 //如果你不希望别人对A类进行扩展,那么可以给A类加上final final class A{ } /* final修饰的类无法继承 class B extends A{ }*/ //方法覆盖 class C{ public final void doSome(){ System.out.println("C"); } } class D extends C{ //无法被覆盖 /*public void doSome(){ System.out.println("D"); }*/ }
该引用只能指向一个对象,并且它只能永远指向该对象。无法再指向其他对象。并且再该方法执行过程中,该引用指向对象之后,该对象不会被垃圾回收器接收直到当前方法结束,才会释放空间。虽然final的引用指向对象A后,不能再重新指向对象B,但是对象内部的值可以修改
package Final; /* final修饰的变量,如果fianl修饰的变量是一个”引用“怎么办? final修饰的引用: 该引用只能指向一个对象,并且它只能永远指向该对象。无法再指向其他对象。 并且再该方法执行过程中,该引用指向对象之后,该对象不会被垃圾回收器接收 直到当前方法结束,才会释放空间 虽然final的引用指向对象A后,不能再重新指向对象B,但是对象内部的值可以修改 */ public class Test02 { public static void main(String[] args){ P p = new P(20); System.out.println(p.age); //------------------------------------- final P p1 = new P(30); System.out.println(p.age); p.age = 60; System.out.println(p.age); //p1 = new P(); 不可以重新new } } class P{ int age; public P() { } public P(int age) { this.age = age; } }
final修饰的变量只能赋值一次
fianl修饰的实例变量,系统不管赋默认值,要求程序员必须手动赋值。这个手动复制,在变量后面直接赋值或者在构造方法中进行赋值也可以。
实例变量在什么时候赋值?
在构造方法执行中进行赋值,(new的时候)
package Final; /* final修饰的实例变量 final修饰的变量只能赋值一次 fianl修饰的实例变量,系统不管赋默认值,要求程序员必须手动赋值 这个手动复制,在变量后面直接赋值或者在构造方法中进行赋值也可以。 实例变量在什么时候赋值? 在构造方法执行中进行赋值,(new的时候) */ public class Test03 { public static void main(String[] args){ } } class User{ //不可以这么修饰变量 final int i; //手动赋值可以 final int age = 1; //以下代码需要组合使用 weight只赋值一次 final double weight; /*public User(){ weight = 80;//赶在系统赋默认值之前赋值就行 }*/ //这样也可以 public User(double D){ this.weight = D; } }
结论:
static final 联合修饰的变量称为“常量”。
每一个单词建议使用大写,每个单词之间使用下划线链接
实际上常量和静态变量医用,区别在于:常量值不能变
常量和静态变量,都是存储在方法区,并且都是在类加载时初始化。
常量一般都是公开的,因为公开也不可以改变
package Final; /* final修饰的变量一边添加在static修饰 结论: static final 联合修饰的变量称为“常量”。 每一个单词建议使用大写,每个单词之间使用下划线链接 实际上常量和静态变量医用,区别在于:常量值不能变 常量和静态变量,都是存储在方法区,并且都是在类加载时初始化。 */ public class Test04 { public static void main(String[] args){ System.out.println(Chiness.COUNTRY); } } class Chiness{ String idCard; String name; String birth; //实例变量,在堆中, //实例变量被final修饰了,说明该实例变量的值不会随着对象的变量而变化 //final修饰的实例变量,一般添加static修饰。 //即使是不会发生改变,最好声明为静态的,节省内存空间 final static String COUNTRY = "China"; //类级别 } class MyMath{ //常量一般都是公开的 public static final double PI = 3.1415926; }
1.1、final修饰的类无法继承。
1.2、final修饰的方法无法覆盖。
1.3、final修饰的变量只能赋一次值。
1.4、final修饰的引用一旦指向某个对象,则不能再重新指向其它对象,但该引用指向的对象内部的数据是可以修改的。
1.5、final修饰的实例变量必须手动初始化,不能采用系统默认值。
1.6、final修饰的实例变量一般和static联合使用,称为常量。
public static final double PI = 3.1415926;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YVk85nKx-1634041323675)(C:/Users/77/Downloads/Documents/09-JavaSE进阶每章课堂画图/01-面向对象/001-抽象类的理解.png)]
类和类之间具有共同特征,将这些类的共同特征提取出来,形成的就是抽象类
类本身是不存在,所以抽象类无法创建对象
抽象类也属于引用数据类型
语法: [修饰符列表] abstract class 类名{ 类体; }
这两个关键字是对立的
抽象方法表示没有实现的方法,没有方法体的方法。
pubilic abstract void doSome();
抽象方法的特点:
1.没有方法体,以分号结尾;
2.前面修饰符列表中有abstract关键字
package Abstract; /* 抽象类: 1.什么是抽象类? 类和类之间具有共同特征,将这些类的共同特征提取出来,形成的就是抽象类 类本身是不存在,所以抽象类无法创建对象 2.抽象类属于什么类型? 抽象类也属于引用数据类型 3.抽象类怎么定义? 语法: [修饰符列表] abstract class 类名{ 类体; } 4.抽象类是无法实例化的,是无法创建对象的,所以抽象类是用来被子类继承的 5.final和abstract是不可以联合使用的 6.抽象类的子类也可以是抽象类 7.抽象类虽然无法实例化,但是抽象类有构造方法,这个构造方法是供子类使用的。 8.抽象类关联到一个概念,抽象方法的概念 抽象方法表示没有实现的方法,没有方法体的方法 pubilic abstract void doSome(); 抽象方法的特点: 1.没有方法体,以分号结尾; 2.前面修饰符列表中有abstract关键字 9.抽象类中不一定有抽象方法,抽象方法必须在抽象类中 */ public class Test01 { public static void main(String[] args){ //无法实例化,不可以创建对象 //Account account = new Account(); } } //final和abstract是不可以联合使用的 /*final abstract class Account{ }*/ abstract class Account{ public Account(String s){ } //不可以不写 public Account(){ } abstract public void A(); } //子类继承抽象类,子类可以实例化对象 /*class CreditAccount extends Account{ }*/ //抽象类的子类可以是抽象类 //构造方法里默认有一个无参构造 //无参构造的第一行为super,super调用父类的无参构造,如果父类没有无参构造(直接提供了一个有参构造,默认没有无参构造),那么会报错 abstract class CreditAccount extends Account{ } //抽象方法必须在抽象方法中 /* class B{ abstract public void A(); }*/
public abstract void doSome();
package Abstract; /* 抽象类: 1.抽象类不一定有抽象方法,抽象方法必须出现在抽象类中 2.重要结论:一个非抽象的类继承抽象类,必须将抽象类中的抽象方法进行实现 这里的覆盖或者说重写,也可以叫做实现 */ public class Test02 { //父类型为抽象类,子类型为非抽象类,这里是否可以使用多态 //面向抽象编程 //a的类型Animal,Animal是抽象的,以后调用的都是a.×× // 面向抽象编程,不要面向具体变成,降低程序的耦合度,提高程序的扩展能力 //这种编程思想符合OCP原则 public static void main(String[] args){//对代码不是很理解的时候,能用多态就用多态 Animal a = new Brid(); //向下转型 a.move(); } } //抽象类 abstract class Animal{ public abstract void move();//抽象方法 } //子类非抽象类 //子类继承父类,父类中有抽象方法,那么子类一定会是抽象类 class Brid extends Animal{ //需要将从父类继承过来的方法进行覆盖/重写,或者也可以叫做“实现” //把抽象方法实现了 public void move(){ System.out.println("move"); }; }
面试题(判断题):java语言中凡是没有方法体的方法都是抽象方法。
不对,错误的。
Object类中就有很多方法都没有方法体,都是以“;”结尾的,但他们
都不是抽象方法,例如:
public native int hashCode();
这个方法底层调用了C++写的动态链接库程序。
前面修饰符列表中没有:abstract。有一个native。表示调用JVM本地程序。
package Interface; /* 接口: 1.也是一种引用数据类型,编译之后也是class字节码文件 2.接口是完全抽象的。(抽象类是半抽象的),或者也可以说接口是特殊的抽象类 3.接口是怎么定定义,语法是什么? [修饰符列表] interface 接口名( ) 定义类 [修饰符列表] class 类名{} 定义抽象类 [修饰符列表] abstract class 类名{} 4.接口支持多继承,一个接口可以继承多个接口 5.接口中只包含两部分内容,一部分是常量,一部分是抽象方法,接口中没有其他内容 6.接口中所有的元素都是public修饰的,接口中所有的东西都是公开的 7.接口中的抽象方法,public abstra 是可以省略的 8.接口中的方法都是抽象方法,接口中的方法不能有方法体。 10.接口中常量的public static final 可以省略 */ public class Test01 { public static void main(String[] args){ // 接口中随便写一个变量就是常量 System.out.println( MyMath.PI); } } interface A { } interface B{ } //接口支持多继承 interface C extends A,B{ } interface MyMath{ //常量 public static final double PI = 3.14; //可以省略public static final double K = 3.1; // public abstract int sum(int a, int b);//抽象方法 //接口当中都是抽象发放,那么在编写代码的时候,public static'可以省略么? int sum(int a, int b); //接口中的方法可以有方法体么? //错误:抽象方法不可以带有主体 /*void doSome(){ }*/ //sub方法 int sub(int a,int b); }
package Interface; /* 接口: 1.类和类之间叫做继承,类和接口之间叫做实现,仍然可以将实现看作继承,继承使用extends,实现使用implements 2.当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现。 */ public class Test02 { public static void main(String[] args){ //接口使用多态 MyMath2 mm = new Ab(); System.out.println(mm.PI); int re = mm.sub(4,3); System.out.println(re); } } interface MyMath2{ public static final double PI = 3.14; int sum(int a, int b); int sub(int a,int b); } //编写一个类(这个类是非抽象类) //需要重写方法,因为Ab不是抽象类 class Ab implements MyMath2{ //实现接口中的方法 public int sum(int a, int b){ return a+b; }; public int sub(int a, int b){ return a-b; }; } //抽象类实现,可以编译通过 abstract class Ac implements MyMath2{ }
接口和接口之间虽然后没有继承关系,但是可以强制转换,但是运行时可能会出现ClassCastException异常,需要于类和类之间的强制转换一样,加上instanceof判断。
package Interface; /* 一个类可以同时实现多个接口 java中的类和类之间只允许单继承,实际上单继承是为了简单出现的 很多情况下会存在多继承,接口弥补了这个缺陷 接口A和接口B虽然没有继承关系,但是可以互相强制转换,但是运行时可能出现ClassCastException异常 无论是向下转型还是向上转向,都必须要有继承关系 没有继承关系,编译器会报错(接口不会) 都需要加上instanceof进行判断,转型之前先进行判断。 */ public class Test03 { public static void main(String[] args){ //多态 AA a = new D(); BB b = new D(); //向下转型 BB b1 = (BB)a; b1.m2(); //向下转型直接转成D D d = (D) a; d.m2(); M m = new E(); //经过测试,接口和接口郑伊健在进行强制类型转换的时候,没有继承关系,也可以强转 //但是运行时可能会出现ClassCastException异常,编译没问题,运行有问题 if(m instanceof K) { K k = (K)m; } } } interface M{ } interface K{ } class E implements M,K{ } interface AA{ void m1(); } interface BB{ void m2(); } interface CC{ void m3(); } //类和接口之间可以进行多实现 //需要对接口中的类进行重写 //类似于多继承 class D implements AA,BB,CC{ //实现A接口的m1 public void m1(){}; public void m2(){}; public void m3(){}; }
package Interface; /* 继承和实现都存在的话:extends关键字在前,implements关键字在后。 */ public class Test04 { public static void main(String[] args){ //创建对象 Flyable f = new Cats();//多态 f.fly(); Flyable f1 = new fish(); f1.fly(); } } class Animal{ } interface Flyable{ void fly(); } class Cats extends Animal implements Flyable{ @Override //重写接口的抽象方法 public void fly() { System.out.println("飞猫"); } } //没有实现接口 class Snake extends Animal{ } class fish extends Animal implements Flyable{ public void fly() { System.out.println("飞