1 this关键字是什么?
在Java中,this关键字代表当前对象。(当前正在操作本方法的对象称为当前对象。)
它在方法内部使用,是对这个方法所属对象的引用;(调用这个方法的对象)
它在构造器内部使用,表示该构造器正在初始化的对象;
this 可以调用类的属性、方法和构造器。
什么时候使用this关键字呢?
当在方法内,需要用到当前对象时(当前对象可以用来调用该类及其从父类继承来的的方法和属性),就用this。
注:
在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性。
当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量。
使用this访问属性和方法时,如果在本类中未找到,会从父类中查找。
使用this 调用本类的构造器:this可以作为同一个类中构造器相互调用的特殊格式。
this(); // 调用本类中的无参构造器
this(xxx,xxx) ; // 调用本类中的带参构造器
注:
可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其他的构造器,且"this(形参列表)“必须声明在类的构造器的首行,且最多只能声明一个"this(形参列表)”!
明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器。
2 package语句
作为Java源文件的第一条语句,指明该文件中定义的类所在的包。
它的格式为:package 顶层包名.子包名 ;
包通常用小写单词标识。通常使用所在公司域名的倒置:com.atguigu.xxx
3 import关键字
为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类或全部类(.*)
语法格式:import 包名. 类名; 或者 import 包名. * ;
4 super关键字
在Java类中使用super来调用父类中的指定操作:(属性、方法、构造器)
super可用于访问父类中定义的属性;
super可用于调用父类中定义的成员方法;
super可用于在子类构造器中调用父类的构造器。
注意:
尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
super的追溯不仅限于直接父类。
调用父类的构造器:
1、子类的构造器都必须直接(super())或 间接(this()) 的调用父类的构造器(父类中的任意构造器即可).
2、子类中所有的构造器默认都会访问父类中空参数的构造器;
3、当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)语句直接或间接的调用父类中响应的构造器。同时,只能”二选一”,且必须放在构造器的首行。(这是为了满足第1条)
4、如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错。(未满足第1条)
this和super:
注:子类对象实例化过程
检查类是否被加载:
类加载过程(
加载(类的加载器、双亲委派模型、自定义类加载器)、连接(检验、准备、解析)、类初始化cinit)
分配内存
初始化零值
设置对象头(类型指针:指向类的元数据,用来确定这个对象属于哪个类;运行时数据:对象的哈希码、对象的GC分代年龄信息、锁状态标志等)
显示初始化、执行初始化块(代码块) 这两者按照定义的先后顺序执行
执行init方法,实例变量初始化
为什么super(…)和this(…)调用语句不能同时在一个构造器中出现?
因为每个this()最终都会直接或者间接执行父类的初始化方法(调用父类构造器);
如果同时出现了super(),那么会再次执行父类初始化。对资源的浪费。
为什么super(…)或this(…)调用语句只能作为构造器中的第一句出现?
因为设计时希望先执行父类的初始化?
示例:
class Creature {
public Creature() {
System.out.println("Creature无参数的构造器");
}}
class Animal extends Creature {
public Animal(String name) {
System.out.println("Animal带一个参数的构造器,该动物的name为" + name);
}
public Animal(String name, int age) {
this(name);
System.out.println("Animal带两个参数的构造器,其age为" + age);
}}
public class Wolf extends Animal {
public Wolf() {
super("灰太狼", 3);
System.out.println("Wolf无参数的构造器");
}
public static void main(String[] args) {
new Wolf();
}}
执行顺序:
new->Wolf()
->super(“灰太狼”, 3);->Animal(String name, int age)->this(name);->Animal(String name)
->如果没有指定super(参数列表),默认调用父类的空参构造器super(),且在第一行->Creature();
->System.out.println(“Creature无参数的构造器”);
->System.out.println(“Animal带一个参数的构造器,该动物的name为” + name);
->System.out.println(“Animal带两个参数的构造器,其age为” + age);
->System.out.println(“Wolf无参数的构造器”);
5 instanceof 操作符
x instanceof A:检验x是否为类A或者类A的子类的对象,返回值为boolean型。
例如:如果CheckAccount是Account的子类,
System.out.println(checkAccount instanceof Account); //true
6 static关键字
需求:有时希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。
如果想让一个类的所有实例共享数据,就用类变量!
类属性、类方法的设计思想:
类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些属性不因对象的不同而改变,将这些属性设置为类属性。相应
的方法设置为类方法。不是说不能改变,而是强调其改变不是由对象决定。
如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。
类属性可能的初始化方式:初始化零值、显示初始化、静态代码块初始化
使用范围:
在Java类中,可用static修饰属性、方法、代码块、内部类。
被修饰后的成员具备以下特点:
随着类的加载而加载(在类加载的连接阶段加载)
优先于对象存在
修饰的成员,被所有对象所共享,在内存中只有一份。
访问权限允许时,可不创建对象,直接被类调用。
注:封装性(权限修饰) 优先级高于 static关键字。
能不能调用,主要是考虑两者在jvm中的生命周期。:
类变量(类属性)由该类的所有实例共享,在内存空间里只有一份。
访问方式:类名.类属性
没有对象的实例时,可以用类名.方法名()的形式访问由static修饰的类方法。
在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。
因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super。
static修饰的方法不能被重写。(因为它属于当前类,在编译时就已经确定了,重写方法往往是为了实现多态,动态绑定。)
在当前类外,实例变量无法调用静态属性和静态方法,只能通过 类名.属性 类名.静态方法
7 final关键字
可以修饰:类、变量(属性、局部变量)、方法。
在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。
final标记的类不能被继承。提高安全性,提高程序的可读性。
例如:String类、System类、StringBuffer类
final标记的方法不能被子类重写。比如:Object类中的getClass()。
final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次。static final:全局常量。
final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,然后才能使用。
注:
如果final变量不是静态的,则可在构造器中给final修饰的“变量”赋值。此时,每创建一个对象时,final常量都可以被赋值一次。
如果final“变量”是静态的,就是全局常量,必须显式初始化或者在静态代码块中初始化。
public static final int HELLO;
public static int totalNumber;
public final int ID;
//如果final“变量”是静态的,就必须显式初始化或者在静态代码块中初始化。
static {HELLO=5;}
public Test1() {
ID = ++totalNumber;
// 可在构造器中给final修饰的“变量”赋值
//每创建一个对象时,final常量都可以被赋值一次
}
public static void main(String[] args) {
Test1 t = new Test1();
System.out.println(totalNumber);
System.out.println(t.ID);
Test1 t1 = new Test1();
System.out.println(totalNumber);
System.out.println(t1.ID);
System.out.println(Test1.HELLO);
final int I = 10;
final int J; J = 20;
}