方法的重写(override/overriding):重新写
- 发生在子父类中,方法名相同,参数列表相同
- 重写方法被调用时,看对象的类型
//能点出什么看引用类型,
//重写方法被调用时,看对象类型
ObserveSubmarine o1=new ObserveSubmarine();
o1.move();//我们点出来的是前一个ObserveSubmarine,但是调用的是后面的ObserveSubarine
SeaObject o2=new ObserveSubmarine();//这里也发生了向上造型
o2.move();//我们是通过引用类型SeaObject点出来的,但是我们调用的是ObserveSubmarine
关于重写的补充
class 学校{
void 学习(){
学习文科;
}
}
//1,我仍旧想要学习文科---------不需要重写
Class Aoo extends 学校{
}
//2,我想改学习理科----------需要重写
Class Aoo extends 学校{
void 学习(){
学习理科;
}
}
//3我想在中餐的基础之上加西餐-------需要重写(先写super,在加入西餐)
Class Aoo extends 学校{
void 学习(){
super.学习();
学习理科;
}
}
对于方法的从写还有两同,两小一大原则
- 两同
- 方法名相同
- 参数列表相同
- 两小
- 派生类方法的返回值类型小于或等于超类方法
- 返回值类型为void和基本类型时,必须相等
- 引用类型时,小于或等于
- 派生类方法抛出的异常小于等于超类方法
- 一大
- 派生类方法的访问权限大于或等于超类方法的(这个很容易想明白,,因为派生类继承超类,它不仅有超类的访问权限,还有派生类自己的访问权限.)
重写与重载的区别
- 重写(override):发生在父子类中,方法名相同,参数列表不同
- 重载(overload):发生在同一类中,方法名相同,参数列表不同.
class Aoo{
void show(){}
}
//下面的类是相对于Aoo类做比较
class Boo{ //既没有重载,也没有重写
void show(){}
}
class Boo extends Aoo{ //发生重写了
void show(){}
}
class Boo{ //既没有重载,也没有重写
void show(int a){}
}
class Boo extends Aoo{ //在此处发生了show的重载
void show(int a){}
}
package与import
1.package:声明包
- 作用:避免类的命名冲突
- 同一个包中的类不能同名,但是不同包中的类可以同名
- 类的全称:包名.类的命,包名常常有层次结构
- 建议:所有的包名小写
2.import导类
同包中的类可以直接访问,而不同包中的类不能直接访问,若想访问:
- 先import导入类,在访问------------这个也是我们建议的写法
- 或类的全称-----------------太繁琐,不建议
访问控制修饰符
- public:公开的
- private:私有的,本类
- protected:受保护的,本类,派生类,同包类---------应用率低
- 默认的:什么都不写,本类,同包类----------java不建议默认权限
说明:
- 类的访问权限只能是public或默认的
- 类中成员的访问权限,如上4种都可以
- 访问权由低到高依次为:private>默认的>protected<public
static:静态的
- 静态变量
- 由static修饰:属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 何时用:所有对象所共享的数据(图片,音频,视频等)
把下面的图结合代码一起看
public class StaticDemo {
public static void main(String[] args) {
Eoo o1 = new Eoo();
o1.show();
Eoo o2 = new Eoo();
o2.show();
Eoo o3 = new Eoo();
o3.show();
System.out.println(Eoo.b); //常常通过类名点来访问
//这里的答案3,因为静态变量在方法区中,只有一份,每次都是调用的是同一份进行++,所有结果是累加
}
}
//演示静态变量
class Eoo{
int a;
static int b;
Eoo(){
a++;
b++;
}
void show(){
System.out.println(a+","+b);
}
}
- 静态方法
- 由static修饰
- 属于类,存储在方法区中,只有一份,
- 常常通过类名点来访问
- 静态方法中没有隐式this传递,所以不能直接访问实例成员
- 何时用:方法的操作与对象无关(方法中不操作对象的属性和行为)
public class StaticDemo {
public static void main(String[] args) {
Foo.test(); //常常通过类名点来访问
}
}
//演示静态方法
class Foo{
int a; //实例变量(对象来访问)
static int b; //静态变量(类名点来访问)
void show(){ //有this
System.out.println(this.a);
System.out.println(Foo.b);
}
static void test(){ //没有this
//静态方法中没有隐式this传递
//没有this就意味着没有对象
//而实例变量a是必须由对象来访问的
//所以如下语句发生编译错误
//System.out.println(a); //编译错误
System.out.println(Foo.b);
}
}
//演示静态方法何时用
class Goo{
int a; //描述的是对象的属性
//在show()方法中访问了对象的属性a,说明该方法与对象有关,不能设计为static方法
void show(){
System.out.println(a);
}
//在plus()方法中不需要访问对象的属性,说明该方法与对象无关,可以设计为static方法
static int plus(int num1,int num2){
int num = num1+num2;
return num;
}
}
- 静态块
- 由static修饰
- 属于类,在类被加载期间自动执行,因为一个类只被加载一次,所以静态块也只执行一次
- 何时用:初始化/加载静态资源(图片,视频,音频)
public class StaticDemo {
public static void main(String[] args) {
Hoo o4 = new Hoo();
Hoo o5 = new Hoo();
Hoo o6 = new Hoo();
}
}
//演示静态块
class Hoo{
static{
System.out.println("静态块");
}
Hoo(){
System.out.println("构造方法");
}
//输出结果如下
/*
静态块
构造方法
构造方法
构造方法
*/
因为静态块只会加载一次.
说了静态块,我们顺便说说静态块,语句块,还有构造方法的先后顺序
package ooday04;
//执行顺序的演示
public class Test {
public static void main(String[] args) {
/*
Ioo o1 = new Ioo();
Ioo o2 = new Ioo();
*/
//Joo o3 = new Joo();
//1)超类静态块 2)派生类静态块
//3)超类语句块 4)超类构造方法
//5)派生类语句块 6)派生类构造方法
Koo o4 = new Koo();
//3)超类语句块 4)超类构造方法
//5)派生类语句块 6)派生类构造方法
Koo o5 = new Koo();
}
}
class Joo{
static{
System.out.println("超类静态块");
}
{
System.out.println("超类语句块");
}
Joo(){
System.out.println("超类构造方法");
}
}
class Koo extends Joo{
static{
System.out.println("派生类静态块");
}
{
System.out.println("派生类语句块");
}
Koo(){
System.out.println("派生类构造方法");
}
}
1.数据(成员变量)私有化,行文(方法)公开化
2,成员变量分两种
- 实例变量:没有static修饰,属于对象,存储在堆中,有几个对象就有几份,通过对象/引用点来访问
- 静态变量:有static修饰,属于类的,存储在方法区中,只有一份,常常通过类名点来访问
- 注意:一般在构造方法中对实例变量进行初始化,在静态块中对静态变量进行初始化
实例变量与静态变量的区别
- 实例变量:是属于对象的,在创建对象时存储在内存堆中,创建多少个对象,则实例变量就会在内存中存在多少分,需要通过引用变量(对象)来访问
- 静态变量:是属于类的,在类被加载时存储在内存方法区中,无论创建多少个对象,静态变量在内存中都只存在一份,通过类名点来访问