一、final关键字
1.1final的基础知识
用来修饰类,方法,变量
final修饰类,该类被称为终极类,不能被继承了
final修饰方法,该方法称为终极方法,不能被重写了
final修饰变量,该变量仅能被赋值一次,且必须被赋值一次!
一般来说,用final来修饰工具类,因为它不需要被继承。
java
public class final_demo1 {
/*
final 修饰静态成员变量
这个变量就成为常量了,用来记住一个固定值,今后不许被修改
通常这个值记录一些系统的配置信息
常量的名称通常全部大写,不同单词用下划线隔开
*/
public static final String SCHOOL_NAME = "张三"; //使用 类名.静态变量 来访问
//final 修饰实例变量 ,通常没有意义,因为这导致类的所有实例的Nick_Name都是一样了
public final String Nick_Name = "猪八戒";
public static void main(String[] args) {
//3.final修饰变量,该变量有且仅有一次赋值
/*
变量有哪些呢?
a:成员变量(写在类中的变量),按有无static修饰又分为静态成员变量,实例成员变量
b:局部变量(写在方法中的变量)
*/
//final修饰rate,只能被赋值一次
final double rate = 3.14;
//rate = 3.01;报错
print(2);
final_demo1 f1 = new final_demo1();
System.out.println(f1.Nick_Name);
System.out.println(final_demo1.SCHOOL_NAME);
}
public static void print(final int z){ // final修饰局部变量z,防止有人在方法当中改z的值
//z=3;报错
System.out.println(z);
}
}
//1.final修饰类,该类不能被继承
final class A{}
//class B extends A{} 报错
//final 修饰方法,该方法不能被重写
class C{
public final void print(){
System.out.println("C");
}
}
/*
class D extends C{
@Override
public void print(){ // 报错
System.out.println("D");
}
}
*/
final的注意事项:
final修饰基本类型的变量,变量存储的数据不能变(int,double等等)
final修饰引用类型 的变量,变量存储的地址 不能改变,但地址指向的内容 可以改变
数组就是一个引用类型的变量
java
//final修饰引用类型的变量,地址不能修改,但是地址指向的对象可以修改
int[] arr = {1,2,3,4};
// arr = {2,3,4,5} 报错,因为修改了地址(一个数组相当于就是一个地址)
arr[0] = 8;
System.out.println(arr[0]);
System.out.println(arr);
1.2常量
使用了 static final修饰的成员变量就是常量。
通常写一个Constant类,用于存储常量,里面的变量都是被static final修饰的,将这个类中的变量值应用于项目的其他地方
二、单例类(设计模式)
2.1什么是设计模式
设计模式就是一种解决问题的方法,总共有20余种,对应各种软件开发时会遇到的问题
对于设计模式,学习两点:1.解决什么问题 ,2.怎么写?
2.2单例设计模式
作用:确保某个类只会创建一个对象
写法:
1.把类的构造器私有化
2.定义一个类的变量(静态变量)用来记住一个类的对象
3.定义一个类方法(静态方法),返回对象
饿汉式单例:
java
//目标:设计单例类
public class A {
//2.定义一个静态变量,记住本类唯一的一个对象
public static A a = new A();
private A (){} //1.私有化构造器。如果不私有化构造器,在外面可以用公开的构造器new无数个A类的实例对象
//3.提供一个公开的静态方法,返回这个类的唯一对象
public static A getInstance(){ //此处static 后的 A就是返回值类型,跟public static int的含义一样
return a;
}
}
java
public class test {
public static void main(String[] args) {
A a1 = A.getInstance();
A a2 = A.getInstance();
System.out.println(a1);
System.out.println(a2); //注意到这俩的地址一样,说明a1,a2是同一个对象
}
}
实现单例的方法很多,上面这个是饿汉式单例,指的是拿对象时,对象早已创建好了。
懒汉式单例:拿对象时,才创建这个唯一对象
写法:
1.把类的构造器私有化
2.定义一个静态变量,用来记住类的唯一对象(在这里只定义,不新建)
3.提供一个静态方法,确保返回的是同一个对象(在这个方法中 如果没有才新建)
java
public class B {
//2.私有化定义一个类的静态变量,用来记住单一对象
private static B b; // b为变量名, B为返回值类型
//1.私有化构造器
private B(){}
//3.提供一个公开的方法,用来第一次时,new出这个对象
public static B getInstance(){
if(b == null){
b = new B();
}return b;
}
}
三、枚举类
3.1认识枚举类
枚举类是一种特殊类,他的写法如下:
java
public enum E { //枚举类一般是public的,它不用class新建,而是用enum。 这是新建枚举类的专用词
x,y,z; //枚举类的第一行,只能罗列待枚举的对象,后面再写其他成员(方法、对象),这是龟腚
//这些名称本质是常量
}
tips:
1.枚举类是最终类,不可被继承
2.枚举类的第一行罗列一些名称,这些都是常量,每个常量都会记住枚举类的一个对象
3.枚举类的构造器是私有的,因此枚举类是一个多例。第一行罗列了几个名称,就只有几个对象,因此若只罗列一个,那枚举类就是个单例类
3.2枚举类的常见应用场景
枚举类可用于信息分类和标志。
java
public class test {
public static void main(String[] args) {
run(E.down);
}
public static void run(E e){
switch (e){
case E.up:
System.out.println("向上移动");
break;
case E.down:
System.out.println("向下移动");
break;
}
}
}
四、抽象类
4.1认识抽象类
使用关键字abstract 修饰 类 或者成员方法,用它修饰类,这个类就是抽象类;用它修饰方法,这个方法就是抽象方法
eg:
java
public abstract class A{
public abstract void test();
}
abstract修饰的抽象方法,只有方法签名(返回值和形参列表),无方法体(就是{ }里面的语句)
tips:
1.抽象类中不一定有抽象方法,但有抽象方法的类必须是抽象类
2.类有的成员,抽象类也可以有(成员变量,成员方法,构造器)
3.抽象类最主要的特点:只能作为父类,而不能创建对象 。仅作为一个特殊的父类,让子类去继承
4.如果一个类要继承抽象类,就必须把抽象类的所有抽象方法重写 ,否则这个类也必须写成抽象类
抽象类的使命就是为了被继承!
4.2使用抽象类的好处
父类知道子类要做的某个行为,但是子类的具体动作不一样,因此父类设计为抽象类,具体的实现交给各个子类。
抽象类是为了多态性而设计的。
java
//要描述每个动物的叫声,使用抽象类
public abstract class Animal {
public abstract void cry();
}
java
public class Dog extends Animal {
@Override
public void cry(){
System.out.println("旺旺");
}
}
4.3 模板方法设计模式
作用:提供一个方法作为完成某类功能的模板,模板方法封装了每个实现步骤,但允许子类提高具体的实现。
提高代码复用,简化字类的设计
五、接口
5.1认识接口
java提供了一个关键字,interface,用来定义接口。
传统接口(jdk8之前):只能定义常量和抽象方法。
注意:接口不能创建对象!!因为他属于抽象类!!
接口是用来被类来实现(implements) 的,实现接口的类称为实现类,一个类可以同时实现多个接口。
语法如下:
java
class 类名 implements 接口1,接口2{}
java
//使用interface关键字来定义接口
public interface interfaceA {
int AGE = 18;
//在接口类中,定义常量时的public static final 可以省略不写
//默认interface类中的都是常量,因此在定义的时候必须赋值,否则会报错
public static final String SCHOOL_NAME = "John";
//接口中,定义抽象方法
// public void sayHello(){}; 定义具体方法,报错
public abstract void Sayhello(); //同样,接口中的public abstract可省略
}
java
public interface interfaceB {
public abstract void SayGoodbye();
}
java
public class test {
public static void main(String[] args) {
System.out.println(interfaceA.SCHOOL_NAME);
C c = new C();
c.SayGoodbye();
c.Sayhello();
}
}
//C被称为实现类,同时实现了多个方法,由于它继承自接口这个抽象类,因此必须重写接口里的所有抽象方法,否则会报错
//实现类实现多个接口,必须重写完所有接口的所有抽象方法,否则必须定义成抽象类
class C implements interfaceA , interfaceB{
@Override
public void Sayhello() {
System.out.println("hello");
}
@Override
public void SayGoodbye() {
System.out.println("goodbye");
}
}
5.2接口的好处
1.弥补了类单继承的不足,一个类可以同时实现多个接口,使得类的角色更多,功能更强大
2.让程序面对接口编程,降低代码的耦合性,便于多个程序员实现业务。
5.3 接口新增的几种方法
1.默认方法,用 default修饰
2.私有方法,用 private修饰
3.类方法,public static修饰
java
public interface A {
//1.默认方法,用default修饰,其实就是普通的实例方法,只是在接口这里要加default
//默认加上public
//如何调用?使用接口的实现类的对象来调用
public default void go() {
System.out.println("A GO!");
print();
}
//2.私有方法,实际上就是私有的实例方法,private来修饰
//如何调用?使用接口中的其他方法调用
private void print(){
System.out.println("A print");
}
// 3.静态方法,默认加上public static
//如何调用,只能使用当前接口名调用
public static void show(){
System.out.println("A show");
}
}
这三种方法自己很少写,会看就行了
5.4接口的几个注意事项
1.接口与接口可以多继承,一个接口可同时继承多个接口。重点
类与类:只能单继承,一个类只能继承另一个类;类与接口:多实现,一个类可实现多个接口
java
interface A{
public void show1();
}
interface B{
public void show2();
}
//1.接口与接口可以多继承,一个接口可同时继承多个接口
interface C extends A,B{
public void show3();
}
//这样一来,假如要同时实现三个接口,只要实现C接口就行了
class D implements C{
@Override
public void show3() {
}
@Override
public void show1() {
}
@Override
public void show2() {
}
}
2.一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时既不支持多继承 ,也不支持多实现 了解
3.一个类继承了父类,又实现了接口,若父类中有同名方法,实现类会优先使用父类的、
4.一个类实现了多个接口,若多个接口中有重名的方法,可以不冲突,这个类重写方法即可(即不要接口的,自己来实现)