一、this
关键字主要有三个应用:
-
this调用本类中的属性,也就是类中的成员变量;
-
this调用本类中的其他方法;
-
this调用本类中的其他构造方法初始化对象,调用时要放在构造方法的首行。
引用成员变量
Public Class Student {
String name; //定义一个成员变量name
private void SetName(String name) { //定义一个参数(局部变量)name
this.name=name; //将局部变量的值传递给成员变量
}
}
this这个关键字其代表的就是当前对象中的成员变量或者方法。为此在上面这个代码中,this.name代表的就是对象中的成员变量,又叫做对象的属性,而后面的name则是方法的形式参数,代码this.name=name就是将形式参数的值传递给成员变量。这就是上面这个代码的具体含义。
作为方法名来初始化对象也就是相当于调用本类的其它构造方法,它必须作为构造方法的第一句。
示例如下
public class Demo{
public String name;
public int age;
public Demo(){
this("微学苑", 3);
}
public Demo(String name, int age){
this.name = name;
this.age = age;
}
public void say(){
System.out.println("网站的名字是" + name + ",已经成立了" + age + "年");
}
public static void main(String[] args) {
Demo obj = new Demo();
obj.say();
}
}
值得注意的是:
-
在构造方法中调用另一个构造方法,调用动作必须在第一行。
-
不能在构造方法以外的任何方法内调用构造方法。
-
在一个构造方法内只能调用一个构造方法。
返回对象的值
this关键字除了可以引用变量或者成员方法之外,还有一个重大的作用就是返回类的引用。如在一个名为student的类中,可以使用return this,来返回某个类的引用。此时这个this关键字就代表类的名称。如student类中,代表的含义就是return student。可见,这个this关键字除了可以引用变量或者成员方法之外,还可以作为类的返回值。
二 、final
被final修饰有三个特性
- 被final修饰的类不能被继承
- 被final修饰的方法不能被重写
- 被final修饰的成员变量不能被重新赋值或修改,只能赋值一次。此时变量就变成了常量
final修饰局部变量
修饰基本类型时,基本类型的值不能发生改变
修饰引用类型时,引用类型的地址值不能发生改变,但是,该对象堆内存的值是可以改变的
class Student {
int age = 10;
}
class FinalTest {
public static void main(String[] args) {
//局部变量是基本数据类型
int x = 10;
x = 100;
System.out.println(x);
final int y = 10;
//这里会报错,无法为最终变量y分配值
//y = 100;
System.out.println(y);
System.out.println("--------------");
//局部变量是引用数据类型
Student s = new Student();
System.out.println(s.age);
s.age = 100;
System.out.println(s.age);
System.out.println("--------------");
final Student ss = new Student();
System.out.println(ss.age);
ss.age = 100;
//这里不会报错,因为final修饰的是引用类型 代表student的地址不可被修改 而该对象堆内存的值是 可以被修改的
System.out.println(ss.age);
//重新分配内存空间
//无法为最终变量ss分配值
ss = new Student(); //这里是错误的
}
}
三、super
总结一下super的用法:
第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,如果该构造方法是无参的,super里面可以不带参数,如果构造方法
是带参构造,那么super里面也需要有对应的参数。同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,用“super.成员变量名”来引用
父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列
表)”的方式访问父类的方法。
class father {
int a= 60;
public father () {
System.out.println("父类无参构造");
}
public father(String name) {
System.out.println("父类带参构造");
}
public void method() {
System.out.println("父类方法1");
}
public void abs() {
System.out.println("没有被重写的父类方法");
}
}
class son extends father {
int a= 10;
public son() {
super();//调用父类的无参构造方法
System.out.println("子类无参构造");
}
public son(String name) {
super (name);//调用父类的带参构造
System.out.println("子类带参构造");
}
public void method() {
super.method();//访问父类成员方法
System.out.println("子类方法1");
System.out.println(super.a);//访问父类成员变量60
System.out.println(a);//子类的成员变量10
super.abs();//实例说明可以用super调用没被子类覆盖重写的父类方法,但是这是没有必要的
//因为可以通过对象名.父类方法名来调用
}
}
public class DEMO {
public static void main(String[] args) {
son s = new son();//
s.method();//调用子类的method
son s2 = new son("aaa");//super的有参调用,这里会初始化有参构造方法
}
}
输出:
输出
父类无参构造
子类无参构造
父类方法1
子类方法1
60
10
没有被重写的父类方法
父类带参构造
子类带参构造
四、static
4.1 static特性
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对,简而言之, static的基本作用就是,方便在没有创建对象的情况下来进行调用(方法/变量),很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问,被static修饰的方法或则变量可以直接通过类名.方法名或者类名.变量名调用,例如
package hello;
class demo{
static String str1 = "hello";
private String str2 = "world";
public void aaa(){
System.out.println(str1);
System.out.println(str2);
}
public static void bbb() {
System.out.println(str1);
}
}
public class Static {
public static void main(String[] args) {
demo s = new demo();
s.aaa();
demo.bbb;//在这里被static修饰的方法名和变量可以直接通过类名.方法名或变量名调用
System.out.println(demo.str1);
}
}
static方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此,静态方法中不能用this和super,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
例如
第12行和13行出错的原因是静态方法bbb()访问了非静态变量str2和非静态变量aaa(),而在第八行中因为aaa是非静态的方法,所以可以自由访问静态变量和静态方法
在这里可以提一下,main方法之所以用static修饰的原因是,在执行main方法的时候没有创建任何对象,所以只能通过类名调用,因此要用static修饰
另外记住,即使没有显示地声明为static,类的构造器实际上也是静态方法
4.3 static变量
static修饰的成员变量:static修饰的成员变量也叫类变量或全局变量,在类被加载时static修饰的成员变量被初始化,与类关联,只要类存在,static变量就存在。一个static变量单独划分一块存储空间,不与具体的对象绑定在一起,该存储空间被类的各个对象所共享。也就是说当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例对象共用同一个static变量。static修饰的成员变量能在创建任何实例对象之前被访问,而不必引用任何对象,也就是说不管创建多少对象,static修饰的变量只占有一块内存。
4.4 static代码块
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
注意,是在类第一次被加载的时候,static代码块才会执行,以后的加载都不会再执行static代码块
示例
package hello;
class demo{
static String str1 = "hello";
private String str2 = "world";
public demo(){
System.out.println(str2);
}
static {
System.out.println("这是static代码块");
}
public void aaa(){
System.out.println(str1);
}
static {
System.out.println("这是第二个静态代码块");
}
public static void bbb(int name) {
System.out.println(str1);
}
}
public class Static {
public static void main(String[] args) {
demo s = new demo();//demo类第一次被加载所以执行静态代码块
demo.bbb(2);
demo q = new demo();//在这里demo类第二次被加载了 所以不再执行静态代码块
q.aaa();
}
}
输出结果
这是static代码块
这是第二个静态代码块
world
hello
world
hello
因为静态代码块只在第一次类加载中执行,所以在以后的类加载中就不再执行静态代码块了, 因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
能通过this访问静态成员变量吗?看下面这个例子
package hello;
class demo{
static int a = 33;
public void printValue(){
int a = 3;
System.out.println("这是this.a:"+this.a);
System.out.println("这是a:"+a);
}
public class Static {
public static void main(String[] args) {
demo s = new demo();
s.printValue();
}
}
输出结果是
这是this.a:33
这是a:3
这里面主要考察队this和static的理解。this代表什么?this代表当前对象,那么通过new 来调用printValue的话,当前对象就是通过new demo生成的对象。而static变量是被对象所享有的,因此在printValue中的this.a的值毫无疑问是33。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。