目录
final关键字
了解到final关键字是学习String类的时候,表示String类是不可变的。
final的基本用法
在Java中,final关键字可以修饰类
,方法
,变量
(包括成员变量和局部变量)
1.修饰类
- 当用final修饰一个类的时候,表示这个类不可以被继承,final修饰的类,所有的成员方法都被隐式的指定为final方法,要谨慎使用final修饰类,防止以后继承的时候,出现问题
2.修饰方法
- 方法锁定,也就是这个方法的的具体任务被确定了,防止继承类修改这个方法的含义
- 提高效率,早期的Java实现版本中,会将final指定的方法内嵌调用,但是如果方法过于庞大,这种方式效率方面就没什么体现了,所以后期的JDK中,不需要使用final修饰方法优化了
- 类的private方法会隐式的指定为final方法
3.修饰变量
- 这种用的较多,对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象(比如String变量)
深入理解final关键字
1.final变量和普通变量的区别
- 当final作用于类的成员变量时(因为局部变量只需要在使用前被初始化赋值即可),成员变量必须在定义或者构造器中被初始化赋值,一旦被赋值,就不可以再更改了。
public class Demo1_final {
public static void main(String[] args) {
String a = "helloworld";
final String b = "hello";
String c = "hello";
String d = b + "world";
String e = c + "world";
System.out.println(a == d); //true
System.out.println(a == e); //false
}
}
区别就是final作用的变量是基本数据类型或String类型时,如果在编译期间就能知道他的确切值, 则编译器就会把它当编译器常量使用,也就是说用到final变量时,直接使用final变量的值(涉及到JVM优化,d的值会在编译器直接去常量池取,也就是a的值),而不需要在运行时。对于d的访问却需要运行时通过链接进行
2.被final修饰的引用变量指向的对象内容可变吗?
- 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象,对象内容是可变的
public class Demo2_final { public static void main(String[] args) { final Num num = new Num(); System.out.println(++num.i); //输出i为1,说明final修饰引用变量,不能指向别的对象,但指向对象的内容是可以修改的 } } class Num{ public int i = 0; }
static关键字
特点
- 一个类的多个对象共享,节省资源空间
- 随着类的加载而加载
- 可以通过类名调用
static的基本用法
在Java中,static的使用场景常常是直接使用类名调用,不用创建对象,static可以修饰类的成员方法
,类的成员变量
,还可以编写static代码块
来优化程序性能
1.static方法
- 一般被成为静态方法,不需要任何对象就可以调用,因此对于静态方法是没有
this
的,由于这个特性,不能在静态方法中访问类的非静态变量和非静态成员方法,因为非静态方法/变量
依赖对象才能调用,但是非静态方法中可以调用静态成员方法/变量,因为非静态方法的使用必须要创建对象来调用。 - Java程序的主方法是static的也好理解了,我们运行程序的时候,不创建对象,main方法就要执行。
2.static变量
- static变量也称静态变量,静态变量被所有的对象所共享,在内存中只有一个副本,它
当且仅当
在类初次加载的时候被初始化,而非静态变量是对象拥有的,创建对象的时候被初始化,存在多个副本,各个对象的副本互不影响
3.static代码块
使用static形成静态代码块,来优化性能,可以放在任何位置,类中可以有多个代码块,在类初次被加载的时候,会按照static块的顺序被执行,且只执行一次
class Person{
private Date birthDate;
private static Date startDate,endDate;
static{ //使用静态代码块一次运行,可以一直使用,不用每次调用isBornBoomer()判断出生年份的时候,都创建两个对象
startDate = Date.valueOf("1946");
endDate = Date.valueOf("1964");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}
深入理解static关键字
1.static会改变类中访问权限吗
答案是不会的,能改变访问权限的只有private,public,protected等几个关键字
public class Demo3_static {
public static void main(String[] args) {
System.out.println(Person.age); //'age' has private access ,意思就是age是私有的,不可视
System.out.println(Person.name);
}
}
class Person{
public static String name = "cfl";
private static int age = 24; //使用了private,而并非是static的问题
}
2.static能作用于局部变量吗
Java中规定,不能使用static修饰局部变量
3.静态变量和成员变量的区别
-
所属不同
- 静态变量属于类,所以也叫类变量
- 成员变量属于对象,也叫对象变量或实例变量
-
内存中位置不同
- 静态变量存储于方法区的静态区
- 成员变量存储于堆内存
-
内存中出现的时间不同
- 静态变量随着类的加载而加载,随着类的消失而消失
- 成员变量随着对象的创建而存在,随着对象的消失而消失
-
调用不同
- 静态变量可以通过类名调用,也可以通过对象调用
- 成员变量必须由对象调用
this关键字
- 初识this关键字是构造方法中,this.name=name
- this关键字的使用环境主要有三种
- 调用本类的中的属性或方法,也就是类的成员变量/成员方法
- 调用本类的其他构造方法,调用时要放在构造方法的首行
- 返回对象的值
1.调用成员变量
public class Demo4_this {
private String name;
public void setName(String name) {
this.name = name;
}
}
上面代码中,this这个关键字其代表的就是对象中的成员变量,后面的name代表的是形参,this.name=name,表示的就是形参传给类的成员变量,也叫对象的属性
2.调用类的构造方法
public class Student {
public Student() {
this("helloWorld"); //调用哪个构造方法是根据参数确定的
}
public Student(String name) { //创建一个带形参的构造方法
}
}
在构造方法中,使用this关键字表示调用类中的构造方法,如果一个类中有多个构造方法,跟普通方法引用构造方法一样,都是通过形参
来调用构造方法的
值得注意的是,使用this关键字调用构造方法,只能在无参构造方法的第一句使用this关键字,不然,Java编译的时候,可能会出现编译错误
3.返回对象的值
- this关键字还有个作用就是返回类的引用。如在代码中,可以使用return this,来返回某个类的引用。此时这个this关键字就代表类的名称。如代码在上面student类中,那么代码代表的含义就是return student
super关键字
- super关键字主要存在于继承关系的子类当中,用于在子类中指向父类对象
- 可以访问父类的属性,方法和构造方法
1.子类的构造函数默认第一行会隐式调用父类的无参构造函数
public class Father {
public Father() { //父类的无参构造方法,不写的话,编译时会默认一个无参的空构造方法
System.out.println("父类的构造方法");
}
}
public class Son extends Father {
public Son() {
//super(); 隐式调用父类的无参构造方法,而且会优先调用父类的构造方法
System.out.println("子类的构造方法");
}
public static void main(String[] args) {
new Son();
}
}
//输出为
父类的构造方法
子类的构造方法
2.子类调用父类的方法
,和父类的属性值
public class Father {
public int num; //定义一个num成员变量
public void test() {
num=100;
}
}
public class Son extends Father {
public int num;
public void test() {
super.test(); //子类中调用父类的方法
num = 200;
System.out.println("子类中的num值:"+num);
System.out.println("父类中的num值:"+super.num); //子类中调用父类的属性值
}
public static void main(String[] args) {
Son son = new Son();
son.test();
}
}
//输出为
子类中的num值:200
父类中的num值:100
3.如果开发者自定义了一个类,没有显示的进行类的继承,那么该类中成员函数是否可以使用super关键字?
可以使用,因为所有的类都是Object类的子类