super关键字
严格来说,super 其实并不是一个引用,它只是一个关键字,super 代表了当前对象中从父类继承过来的那部分特征。this 指向一个独立的对象,super 并不是指向某个“独立”的对象,假设张大明是父亲,张小明是儿子,有这样一句话:大家都说张小明的眼睛、鼻子和父亲的很像。那么也就是说儿子继承了父亲的眼睛和鼻子特征,那么眼睛和鼻子肯定最终还是长在儿子的身上。假设this指向张小明,那么 super 就代表张小明身上的眼睛和鼻子。换句话说 super 其实是 this 的一部分。如下图所示:张大明和张小明其实是两个独立的对象,两个对象内存方面没有联系,super 只是代表张小明对象身上的眼睛和鼻子,因为这个是从父类中继承过来的,在内存方面使用了 super 关键字进行了标记,对于下图来说“this.眼睛”和“super.眼睛”都是访问的同一块内存空间。super 不是引用。super也不保存内存地址,super也不指向任何对象。
简单理解
- super :代表父类的存储空间标识(可以理解为父亲的引用)。
父类空间优先于子类对象产生
在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空 间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构 造方法调用时,一定先调用父类的构造方法。理解图解如下:
下面super 和 this 可以对比着学习:
this
- this 是一个引用,保存内存地址指向自己。
- this 出现在实例方法中,谁调用这个实例方法,this 就代表谁,this 代表当前正在执行这个动作的对象。
- this 不能出现在静态方法中。
- this 大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略。
- “this(实际参数列表)”出现在构造方法第一行,通过当前的构造方法去调用本类当中其它的构造方法。
super
- super能出现在实例方法和构造方法中。
- super的语法是:“super.”、“super()”
- super不能使用在静态方法中。
- super. 大部分情况下是可以省略的。
- “super(实际参数列表);”只能出现在构造方法第一行,这种用法是通过当前的构造方法调用父类的构造方法。目的是:创建子类对象的时候,先初始化父类型特征。
super可用于在子类构造器中调用父类的构造器
- super(参数列表)语句指定调用父类中相应的构造器。
注意事项:
- 子类中所有的构造器默认都会访问父类中空参数的构造器,无论是怎样折腾,父类的构造方法是一定会执行的
package demo01;
/*
程序的输出结果
1
3
6
5
4
在java语言中不管是是new什么对象,最后老祖宗的Object类的无参数构造方法
一定会执行。(Object类的无参数构造方法是处于“栈顶部”)
栈顶的特点:
最后调用,但是最先执行结束。
后进先出原则。
大家要注意:
以后写代码的时候,一个类的无参数构造方法还是建议大家手动的写出来。
如果无参数构造方法丢失的话,可能会影响到“子类对象的构建”。
*/
public class Demo01Super{
public static void main(String[] args){
new C();
}
}
class A extends Object{
public A(){
System.out.println("1"); //1
}
}
class B extends A{
public B(){
System.out.println("2"); //2
}
public B(String name){
System.out.println("3"); // 3
}
}
class C extends B{
public C(){ // 这个是最先调用的。但是最后结束。
this("zhangsan");
System.out.println("4");//4
}
public C(String name){
this(name, 20);
System.out.println("5");//5
}
public C(String name, int age){
super(name);
System.out.println("6");//6
}
}
- this()和super() 不能共存,它们都是只能出现在构造方法第一行。
- 当一个构造方法第一行:既没有this()又没有super()的话,默认会有一个super();表示通过当前子类的构造方法调用父类的无参数构造方法。所以必须保证父类的无参数构造方法是存在的。
“super(实参)”到底是干啥的?
- 在构造方法执行过程中一连串调用了父类的构造方法,父类的构造方法又继续向下调用它的父类的构造方法,但是实际上对象只创建了一个。
- super(实参)的作用是:初始化当前对象的父类型特征。并不是创建新对象。实际上对象只创建了1个。
this和super的区别
super. 什么时候不能省略?
当子父类出现同名成员时,可以用super表明调用的是父类中的成员
super 使用在实例方法中
- super可用于访问父类中定义的属性
- super可用于调用父类中定义的成员方法
/*
在父和子中有同名的属性,或者说有相同的方法,
如果此时想在子类中访问父中的数据,必须使用“super.”加以区分。
super.属性名 【访问父类的属性】
super.方法名(实参) 【访问父类的方法】
super(实参) 【调用父类的构造方法】
*/
public class SuperTest07{
public static void main(String[] args){
/*
Cat move!
Cat move!
Animal move!
*/
Cat c = new Cat();
c.yiDong();
}
}
class Animal{
public void move(){
System.out.println("Animal move!");
}
}
class Cat extends Animal{
// 对move进行重写。
public void move(){
System.out.println("Cat move!");
}
// 单独编写一个子类特有的方法。
public void yiDong(){
this.move();
move();
// super. 不仅可以访问属性,也可以访问方法。
super.move();
}
}
注意:
- 尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
- super的追溯不仅限于直接父类
- super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识
子类对象的实例化过程
final:关键字
学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承 API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java提供了 final 关键字, 用于修饰不可改变内容。在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。
final修饰类
含义:
final标记的类不能被继承。提高安全性,提高程序的可读性。例如 String类、System类、StringBuffer类 都使用了final修饰
final class A{
}
class B extends A{ //错误,不能被继承。
}
中国古代,什么人不能有后代,就可以被final声明,称为“太监类”!
final修饰方法
含义:
final标记的方法不能被子类重写。比如:Object类中的getClass()。
class A {
public final void print() {
System.out.println("A");
}
}
class B extends A {
public void print() { // 错误,不能被重写。
System.out.println("11");
}
}
final修饰基本类型局部的变量
含义:
基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。我们称之为常量,常量名要大写,内容不可修改。——如同古代皇帝的圣旨。
public class Demo02 {
public static void main(String[] args) {
// 声明变量,使用final修饰
final int a;
// 第一次赋值
a = 44;
// a = 233; 第二次赋值 报错
//声明变量,直接赋值,使用final修饰
final int b = 10;
// 第二次赋值 b = 20; 报错,不可重新赋值
}
}
final修饰成员变量
系统不会在给其赋值,必须由程序员手动赋值,成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:
显示初始化;
public class User {
final String USERNAME = "张三";
private int age;
}
构造方法初始化
public class Demo02 {
final String USERNAME;
private int age;
public Demo02(String username, int age) {
this.USERNAME = username;
this.age = age;
}
}
总结:
因为final修饰的成员变量不可改变,我们一般 和 static 联合起来使用。
static final int i = 10;//全局常量
常量名要大写,下划线链接各个单词。常量和静态变量都存储在方法区,并且都是在类加载时初始化。
注意:final不能修饰构造方法
关键字:package
package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。它的格式为:
- package 顶层包名.子包名 ;
package pack1.pack2; //指定类PackageTest属于包pack1.pack2
- 包对应于文件系统的目录,package语句中,用 “.” 来指明包(目录)的层次;
- 包通常用小写单词标识。通常使用所在公司域名的倒置:com.wrg.xxx
包的作用:
- 包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式
- 包可以包含类和子包,划分项目层次,便于管理
- 解决类命名冲突的问题
- 控制访问权限
JDK中主要的包介绍
Java中的常用包 |
说明 |
java.lang | 包含一些Java语言的核心类,如String、Math、Integer、 System和Thread,提供常用功能 |
java.net | 包含执行与网络相关的操作的类和接口。 |
java.io | -包含能提供多种输入/输出功能的类。 |
java.util- | 包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。 |
java.text | 包含了一些java格式化相关的类 |
java.sql- | 包含了java进行JDBC数据库编程的相关类/接口 |
java.awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 |
注意事项
- 写项目时都要加包,不要使用默认包。
- com.gao和com.gao.car,这两个包没有包含关系,是两个完全独立的包。只是逻辑上看起来后者是前者的一部分。
关键字:import
为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类或全部类(.*)。import语句告诉编译器到哪里去寻找类。语法格式:
- import 包名. 类名;
import pack1.pack2.Test; //import pack1.pack2.*;表示引入pack1.pack2包中的所有结构
注意:
- 在源文件中使用import显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
- 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的是哪个类。
- 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
- import static组合的使用:调用指定类或接口下的静态的属性或方法
-
静态导入(static import)是在JDK1.5新增加的功能,其作用是用于导入指定类的静态属性和静态方法,这样我们可以直接使用静态属性和静态方法