1 final
1.1是什么
final 是个修饰符,表示最终的,不可更改的
1.2能做什么
final修饰的类 不能被继承
final 修饰的成员方法 不能被覆写
final 修饰的变量 不能二次赋值 没有默认值 必须显式赋值
一般我们把final修饰的静态变量叫做常量 也就是 public static final 数据类型 变量名 = 值 ;
1.3怎么用
package _01_Final;
/**
*
* @author SEC90 2022年1月12日上午9:10:28
*/
public class Final_01 {
//final 修饰的成员变量 不能二次赋值 没有默认值
// final int age ;
//一般我们把final修饰的静态变量叫做常量,psf会一起出现
//一般以大写字母命名
public final static int AGE= 1;
//修饰列表 相互之间无先后顺序 互换位置无影响
public static void main(String[] args) {
//final 修饰的变量 不能二次赋值
// final int i = 1;
// i = 2;
}
}
//final 修饰的类不能被继承
//final class A{
//
//}
//class B extends A{
//
//}
// * final 修饰的成员方法 不能被覆写
//class A{
//public final void m1() {
//
// }
//}
//
//class B extends A{
// @Override
// public void m1() {
//
// }
//}
package _01_Final;
public class Final_02 {
public static void main(String[] args) {
final Customer a = new Customer("张三",18);
//age和name 没有被final修饰,final只修饰了c,即c这个对象,是保存age和name的地址,不是两者的变量
a.age = 19;
a.name = "李四";
//不能更改c,因为a被final修饰了
// a = null;
}
}
class Customer{
String name;
int age ;
public Customer(String name , int age) {
this.name= name;
this.age= age;
}
}
2 多态
2.1 是什么
父类引用指向子类
父类引用 : 指的是 用父类声明的引用类型变量
指向 : 通过内存地址 可以找到哪个对象
子类对象 : new 子类 创建的堆内存对象
子类 变量 = new 子类();
Cat c = new Cat();
父类类型 变量名 = new 子类();
Animal a = new Cat();
多态性
同一操作 作用于不同的对象,可以有不同的解释,产生不同的结果,这就是多态性
当一件事会有多种不同实现方式的时候 我们选择依赖高层 来拥抱多宗种变化
本质还是降低类和细节直接的耦合度
2.2相关知识
1 单一职责原则 : 功能单一, 只拥有一种变化, 一个方法尽量和别的方法没有关联 一个类和一个方法只做一件事,这样内聚性更强
内聚性强就是指聚合性强,优点任意插拔,任意拼凑 灵活性 可变化性强
聚合 : 组成一个整体的各个部件互不影响,不依赖整体
组合 : 组成一个整体的各个部件受整体影响,整体消亡,部件也消亡
2 里式替换原则 : 能使用父类的情况下,一定可以使用子类(子类功能一定比父类功能强)
3 依赖倒置原则 : 序要依赖于抽象接口,不要依赖于具体实现, 细节应该依赖于抽象,抽象不应该依赖细节
4 接口隔离原则
5 迪米特法则 : 最少知识原则 只和直接类关联 不管其他类
6 开闭原则 : 对修改关闭 对扩展开放
2.3 优点
同一操作,作用于不同对象,可以有不同的解释,产生不同的结果,这就是多态性
当一件事会有多种不同实现方式的时候,我们选择依赖高层,来拥抱多种变化
本质还是降低类和细节之间的耦合度.
package _02_Poly;
/**
* @author SEC90
*2022年1月12日上午9:34:24
*/
public class Poly_01 {
public static void main(String[] args) {
// Cat c1 = new Cat();
//多态
Animal a1 = new Cat();
a1.eat();
a1 = new Dog();
a1.eat();
}
}
class Animal{
public void eat() {
System.out.println("动物吃东西");
}
public void move() {
System.out.println("动物在移动");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
package _02_Poly;
public class Poly_02 {
public static void main(String[] args) {
Animal a = new Cat();
test(a);
Animal a1 = new Dog();
test(a1);
}
//要求 要求能够接收Cat对象,并调用该对象的eat方法
// public static void test(Cat cat) {
// cat.eat();
// }
//要求 要求能够接收Dog对象,并调用该对象的eat方法
// public static void test(Dog dog) {
// dog.eat();
// }
//要求 : 要求能够接收所有的动物,并调用该对象的eat方法
public static void test(Animal a) {
a.eat();
}
}
2.4 缺点
package _02_Poly;
/**
* 多态的缺点 : 丢失子类特有的属性
*
* 多态进行属性调用:
* 1 如果父类没有,直接报错 不管子类有没有
2 如果父类有 子类没有 直接执行父类
3 父类和子类都有 成员方法执行子类 因为成员方法可以覆写 其他都执行父类
*
* 多态又叫向上转型
*
* @author SEC90
*2022年1月12日上午10:43:28
*/
public class Poly_03 {
public static void main(String[] args) {
//多态
SupClass supClass = new SubClass();
//父类子类都有 的成员方法 执行子类
supClass.m1();
// 父类没有子类有 报错 访问不了
// supClass.m2();
//父类有 子类没有 执行父类
supClass.m3();
// 父类子类都有 静态方法 执行父类
// supClass.m4();
//成员变量 执行父类
System.out.println(supClass.i);
//此时 由于多态原因 子类特有属性访问不到 想要访问也行 先进行向下转型
//先发生向上转型才能发生向下转型
//强制类型转换,不再是多态
SubClass subClass = (SubClass) supClass;
subClass.m2();
//如果没有发生向上转型 直接向下转型 会报错
//_02_Poly.SupClass cannot be cast to _02_Poly.SubClass类型转换异常
// SupClass supClass2 = new SupClass();
// SubClass subClass2 =(SubClass) supClass2;
// subClass2.m2();
//instanceof : 判断 某个对象是否有某个类实例化而来
if (supClass instanceof SubClass){
//如果是 在向下转型 不是 就不转 可以避免类型转换异常
@SuppressWarnings("unused")
SubClass subClass2 = (SubClass) supClass;
}
}
}
class SupClass{
int i = 1;
public static void m4() {
System.out.println("父类静态m4");
}
public void m1() {
System.out.println("父类成员m1");
}
public void m3() {
System.out.println("父类成员m3");
}
}
class SubClass extends SupClass{
public static void m4() {
System.out.println("父类静态m4");
}
public void m1() {
System.out.println("子类成员m1");
}
public void m2() {
System.out.println("子类成员m2");
}
}
package _02_Poly;
/**
* 多态的几种形式
*
* 父类引用 指向 子类对象
*
* @author SEC90 2022年1月12日下午8:13:24
*/
public class Poly_04 {
@SuppressWarnings("unused")
public static void main(String[] args) {
//直接多态
Sup sup = new Sub();
//形参和实参 方法参数列表为父类类型 调用方法传入子类对象
m1(new Sub());
//返回值多态 返回值类型时父类类型 但是返回之类对象
Sup result = m2();
}
public static void m1 (Sup sup){
}
public static Sup m2() {
return new Sub();
}
}
class Sup{
}
class Sub extends Sup{
}
package _03_Abstract;
/**
* abstract : 修饰符, 修饰类 是抽象类,修饰方法是抽象方法
*
* 抽象类,不能实例化对象
*
* 抽象方法没有方法体,值定义功能 没有功能的实现 并且抽象方法必须在抽象类中 抽象类中可以有抽象方法,其他和实体类一样,可以没有抽象方法
*
* final和abstract不能同时出现
*
* @author SEC90 2022年1月12日下午2:16:37
*/
public class Abstract_01 {
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();
animal = new Dog();
animal.eat();
}
}
abstract class Animal {
/**
* 动物吃饭功能,抽象方法
*/
public abstract void eat();
public void m1() {
}
}
class Cat extends Animal {
// 实现
@Override
public void eat() {
System.out.println("Cat eat fish");
}
}
class Dog extends Animal {
// 实现
@Override
public void eat() {
System.out.println("Dog eat meat");
}
}
package _04_Interface;
/**
* 接口
没有构造方法也不能生成对象
可以理解为完全抽像的一个类 里面只有抽象方法和常量
但是从1.8开始 , 允许出现 静态方法和默认方法
语法 修饰符 interface 接口名{}
接口中的抽象方法 不需要加abstract修饰 方法默认都是public abstract
接口中 没有变量 只有常量 并且 public static final 可以省略
类和接口不再是继承关系 由extends 换成了 implements (实现)
接口名 变量 = new 子实现类() 也是会发生多态的
一个类只能继承一个类 但是可以实现 N 个接口 以逗号隔开 可以解决单继承功能变弱问题
class 类名 implements 接口1,接口2,....{}
接口和接口之间 是多继承,多个以逗号隔开
interface 接口名 extends 父接口名1,父接口名2,...{}
一个类 如果实现了一个接口 那么必须实现接口中所有的抽象方法 否则该类需要加abstract修饰
一个抽象类 实现一个接口 可以实现0~N个抽象方法
1.7只能有抽象方法
1.8 可以有静态方法 可以有default 方法(或理解为成员方法即可)
静态方法调用接口名即可
default方法需要通过自实现类调用 可以覆写
1.9开始支持private方法
如果接口和抽象类都能做到一件事 优先使用接口 因为这样会保留类的继承
*
* @author SEC90
*2022年1月12日下午2:29:31
*/
public class Interface_01 {
}
interface A{
public static final String name = "xx";
//psf可以省略
int age = 12;
public abstract void m1();
//public 和 abstract 可以省略
void m2();
public default void m3() {
System.out.println("默认方法");
}
public static void m4() {
System.out.println("静态方法");
}
}
interface B{
}
//多继承
interface C extends A,B{
}
//多实现 需要实现所有的 抽象 方法
class D implements A,B,C{
@Override
public void m1() {
}
@Override
public void m2() {
}
}
//抽象类 实现0~N个抽象方法
abstract class E implements A,B,C{
}
package _05_Object._01_Equals;
/**
*
* Object 是所有类的祖宗 是Java中提供的根类
*
* 一个类没有显示继承另一个类的时候 默认继承Object
*
* Object xx = new xxx(): 是可以发生多态的
*
* == : 比较基本类型的时候 比较值的大小 但是比较引用类型时 比较的是内存地址
*
* 而内存比较是没有任何价值的 我们一般会比较两个对象的属性值 是否一致 而不是比较两个对象地址是否一致
*
* Equal() : 该方法设计目的 用来比较两个对象是否相等 , 但是默认比较地址
*
* Java中Object 里面的equal 方法 默认比较内存地址 (== ) 需要根据需求覆写
*
* @author SEC90 2022年1月12日下午3:15:11
*/
public class Equals_01 {
public static void main(String[] args) {
Student student = new Student(1, "xx");
Student student2 = new Student(1, "xx");
//false
System.out.println(student == student2);
//true
System.out.println(student.equals(student2));
}
}
class Student {
int id;
String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
// 需求 如果两个学生的ID相同 就认为这两个学生相同
// 需求 如果两个学生的ID和名字相同 就认为这两个学生相同
@Override
public boolean equals(Object obj) {
// 判断是不是同一个对象
if (this == obj) {
return true;
}
// 判断obj是否由Student实例化而来
if (obj instanceof Student) {
// 向下转型
Student s = (Student) obj;
// 对比 像同为TRUE
if (this.id == s.id&&this.name == s.name){
return true;
}
}
return false;
}
}
package _05_Object._01_Equals;
public class Equals_02 {
public static void main(String[] args) {
String s1 = new String("xxx");
String s2 = new String("xxx");
// false
System.out.println(s1 == s2);
// true 因为String中 覆写了 equals方法
System.out.println(s1.equals(s2));
}
}
package _05_Object._02_Finalize;
/**
*finalize : 该方法会在垃圾被回收的时候自动调用,无序程序员手动调用
*
* 垃圾 : 当一个对象,没有更多引用指向它的时候,该对象被视为垃圾数据(就是创建了一个对象,谁也找不到他)
*
* protected void finalize() throws Throwable { }
* Object中的finalize方法,什么也没有做,需要自己根据需求进行重
* @author SEC90
*2022年1月12日下午9:32:30
*/
public class Finalize_01 {
@SuppressWarnings("unused")
public static void main(String[] args) {
Person p = new Person();
// finalize方法没有回收功能,手动调用的话,只是单纯的方法调用而已
// p.finalize();
p = null;
// 程序员可以建议进行垃圾回收
// System.gc();
// for (int i = 0; i < 10000000; i++) {
// new Person();
// }
}
}
class Person {
@Override
public void finalize() {
System.out.println(this + "我要被回收了");
}
}
package _05_Object._03_ToString;
/**
* toString : 代表了当前对象的字符串表示形式
*
* 当我们打印一个引用类型变量的时候,会自动调用该对象的toString方法
*
* 而 Object 中默认的toString方法 是打印该对象的内存地址(hash值
* @author SEC90
*2022年1月12日下午9:34:19
*/
public class ToString_01 {
public static void main(String[] args) {
Person p1 = new Person("张三", 18);
System.out.println(p1);
System.out.println(p1.name + ":" + p1.age);
}
}
class Person {
public String toString() {
return this.name + ":" + this.age;
};
String name;
int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
本文深入讲解Java中的final修饰符及多态概念,包括final的用途、多态的应用场景及其优缺点,并探讨抽象类、接口、对象等核心内容。
2124

被折叠的 条评论
为什么被折叠?



