目录
5、关键字
5.1、类和对象
- class:定义一个类
- new:创建对象
- extend:类的继承
- interface:定义接口
- implement:实现接口
- abstract:抽象类
5.2、权限控制
权限修饰可以用来修饰类的内部结构:属性、方法、构造器、内部类。
而类只能用 public 和 default 这两个来修饰。
权限修饰在一个位置只能出现其中之一。
访问级别是最高的是public表示所有的都可以访问,其次是protected、默认的,最低的是private表示除了自身外都不可访问。
5.3、static
static主要的作用就是用来区分成员变量、方法、内部类、代码块到底属于类本身还是属于类的实例对象。
虽然static非常有用,但过度使用会导致代码之间的耦合过高,并可能降低代码的测试性和灵活性。例如,静态方法无法被覆盖,因此在继承时可能不如实例方法灵活。此外,静态变量如果不被适当管理,也可能导致内存泄漏等问题。因此,合理使用static关键字是关键。
是否可以在static修饰的方法内调用非static方法?
分两种情况描述。
1、如果在静态方法中显示的创建了对象的实例,因为对象已经创建了,所以此时可以调用非static方法
2、在静态方法中没有创建对象实例而直接调用非静态方法,这种情况是不可以的,非静态方法需要创建对象才会分配空间,而静态方法在类加载时便分配了空间,而此时未创建对象,所以在调用时会出现异常。
5.4、final
在 Java 中,final 是一个修饰符,可以用来修饰类、方法和变量。它的含义是“最终的、不可改变的”。
5.4.1、修饰变量
使用final修饰变量后,变量一旦被赋值,其值就不能再被改变。final变量可以是成员变量、局部变量或类变量。
-
final修饰类变量:必须在静态初始化块中或在声明时就进行初始化。
-
final修饰成员变量:必须在构造器执行结束前被初始化(直接指定初始值、代码块中、构造方法中)
-
修饰局部变量:系统不会为局部变量进行默认的初始化,所以局部变量必须显式赋初值后才能使用, 可以在定义时直接赋初值,也可以在使用前再赋初值,但是只能赋一次。
对于Java中的普通成员变量(非final修饰),如果没有显式初始化,它们会被自动赋予默认值。
然而对于final成员变量,必须在声明时或者构造器中进行初始化,且只能初始化一次,否则编译器将报错,因为final变量一旦被赋值后就不允许再被修改,所以必须确保其在使用前已正确初始化。
5.4.2、宏替换
对于final 修饰的变量,只要满足三个条件,它就不再是一个变量,而是一个直接量,编译器会把程序中用到该变量的地方直接替换成相应的值。
- 使用final 修饰
- 在定义时直接指定初始值
- 该初始值在编译时可以直接被确定
在Java中直接赋值、被赋值的表达式是基本的算术表达式、是字符串连接运算,没有调用变量方法时,编译器会把这些 final 修饰的变量当成直接量处理。
5.4.3、修饰类、方法
当修饰一个类时,这意味着这个类不能被继承。
- 当一个类设计为一个包含静态方法的工具类时,通常会声明为final
- 当你想确保类的实现不被更改,并且出于安全考虑,比如不允许改变特定的行为或逻辑。
修饰方法时,这个方法不能被其子类重写。如果一个类不是final类,但你希望确保某些核心功能的实现不被子类改变,可以将这些方法单独声明为final。
public class Animal {
public final void breathe() {
System.out.println("Breathing air");
}
}
public class Dog extends Animal {
// 下面的尝试将会引发编译错误:
// public void breathe() {
// System.out.println("Breathing fast");
// }
}
- 保护方法不被修改的语义,尤其是当方法涉及到安全性、权限检查或特定的执行逻辑时。
- 在设计类的时候,确保核心行为不被更改,同时允许其他功能通过继承进行扩展
final修饰符在类和方法层面上提供了一种有效的机制来控制继承和多态,确保了软件组件的稳定性和可预测性。使用final可以避免不必要的继承和潜在的复杂性增加,有助于维护清晰和简洁的代码结构。
5.4.4、不可变类
在Java中不可变类指的是其实例一旦被创建,其状态(即实例变量的内容)就不能被修改的类。使用不可变类可以提高程序的安全性和简洁性,并且由于不可变对象是线程安全的,这使得它们非常适合在多线程环境下使用。
在Java中像String、包装类等,这些类都是不可变类,一旦创建了不可变类的实例后,其实例变量就不可改变。创建不可变类需要遵循:
- 将类声明为final
- 类内所有成员变量需要private和final修饰
- 提供一个带参数的构造器,根据构造器初始化类中的成员变量
- 为成员变量提供get 方法,不提供set 方法
- 在需要时通过返回新对象而不是修改当前对象
- 确保成员变量的类也是不可变的:
- 有必要的话,可以重写Object的hashCod 和 equals 方法
在设计不可变的类时,需要注意引用类型的成员变量,如果引用类型的成员变量是可变的,那就必须采取措施保护该成员变量所引用的对象不会被修改,否则该类就不是不可变类。
1、final:最终的。
修饰变量时必须显式赋初始值,且赋值后不可再更改(基本数据类型是值不可改,引用数据类型是不能再指向其他对象,但是对象内的数据是可改的)。
修饰方法时方法时不能重写
修饰类时类不能被继承。
和Static同时使用,是创建常量。
2、finally是处理异常时配合try、catch一起使用,用于存放那些无论是否出现异常都一定会执行的代码,通常用于释放锁、数据库连接等资源。
3、finalize是Object类的一个方法,是垃圾回收机制的一部分,当对象被回收时,垃圾回收处理器调用此方法。JVM不能保证此方法总被调用。在 Java 9 中该方法已经被标记为废弃,并添加新的 java.lang.ref.Cleaner,提供了更灵活和有效的方法来释放资源。
5.5、this、super
5.5.1、this
在Java中有一个关键字 this,它就是指对象本身,也就是正在执行的方法所属对象的引用。
- 引用当前对象的属性:当方法的参数或局部变量与类的成员变量同名时,Java往往采用就近原则,先使用局部变量,此时必须添加 this来使用成员变量。
- 在构造器中引用其他构造器:在一个类中可以有多个构造器,this()可以用来从一个构造器中调用另一个构造器,通常用于构造器重载。这样做可以提高代码的复用性。但是需要注意this需要写在构造方法内的第一行
- 在方法中调用自身方法:可以直接省略this,当然这个省略只是书写上的省略,实际上this仍然存在
- 传递当前对象实例:将当前对象作为参数传递给其他方法,或者返回当前对象实例。
- 在内部类中引用外部类的实例:在内部类中,引用的是内部类的实例。如果需要引用外部类的实例,可以使用 OuterClass.this。
public class Person{
String name;
int age;
public Person(String name,int age){
//像这种,参数名和实例变量名字相同时就可以使用this关键字区分
//this.name 表示的就是对象的属性,没带this的就是参数
this.name = name;
this.age = age;
}
public Person(){
//调用自身带参的构造方法
this("张三",20);
}
public void say(){
System.out.println("说话.....");
}
public void exercise(){
System.out.println("运动.....");
//在方法中可以使用this调用其他方法
this.say();
//省略掉this也可以
say();
//也可以调用自身属性
System.out.println("名字是:"+this.name);
}
}
需要注意的是this关键代表的是对象本身,所以static修饰的方法中不能使用this关键字
5.5.2、super
super:是对上级空间的引用,即对父类空间的引用(并不能代表对象,只是代表一个对象中的一块内存而已),super可以调用父类的属性方法。子父类存在着同名的成员(包括变量和方法)时,在子类中默认是访问子类的成员,可以通过super关键字指定访问父类的成员。
- 可用于访问父类中定义的属性(如果子类没有和父类重名的属性可以不用写super,如果存在重名则必须显式的使用super)
- 可用于调用父类中定义的方法(如果子类没有和父类重名的方法可以不用写super,如果存在重名则必须显式的使用super)
- 可用于在子类构造器中调用父类的构造器(写在第一行)
//定义一个动物类
public class Animal {
String name;
public Animal(){
System.out.println("Animal");
}
public Animal(String name){
this();
this.name = name;
}
}
//在定义一个子类Dog
public class Dog extends Animal {
String name;
public Dog(String name){
//调用父类构造方法
super("动物");
//调用父类的属性
System.out.println(super.name);
//自己的属性
this.name = name;
System.out.println("Dog:"+name);
}
}
super与this关键字不能同时出现在同一个构造函数中调用其他的构造函数。因为两个语句都需要第一个语句。但是子类实例化前需要先实例化父类,所以如果都不调用,则默认调用父类的无参构造。