Java知识点(九):方法的重写、重写和重载的区别、package、import、public、private、protected、默认访问控制符、static、final
文章目录
Java语言基础
包括方法的重写(Override)、重写和重载的区别、访问控制(package、import、public、private、protected、默认访问控制符、访问控制修饰符对比)、静态变量、静态方法、静态块、成员变量和静态变量的区别、修饰成员变量、修饰方法、修饰类。
一、方法的重写(Override)
1)子类可以重写(覆盖)继承来自父类的方法,即方法名和参数列表与父类的方法相同,但实现方式不同
2)当子类对象的重写方法被调用时,无论是通过子类的引用调用还是通过父类的引用调用,运行的都是子类重写后的方法
public class Ooo {
public static void main(String[] args) {
Aoo o1 = new Boo();
Boo o2 = new Boo();
o1.show(); //结果为Java!
o2.show(); //结果为Java!
}
}
class Boo extends Aoo{
void show() {
System.out.println("Java!");
}
}
class Aoo{
void show() {
System.out.println("Python!");
}
}

3)在子类重写的方法中,可以通过super关键字调用父类的“原始”方法
public class Ooo {
public static void main(String[] args) {
Aoo o1 = new Boo();
o1.show(); //Python!Java!
}
}
class Boo extends Aoo{
void show() {
super.show(); //调用父类show方法,执行子类show方法会打印出Python!Java!
System.out.print("Java!");
}
}
class Aoo{
void show() {
System.out.print("Python!");
}
}

代码示例:
public class OverrideDemo {
public static void main(String[] args) {
Aoo o1 = new Aoo();
o1.show(); //父类show
System.out.println();
Boo o2 = new Boo();
o2.show(); //父类show 子类show!
System.out.println();
Aoo o3 = new Boo();
o3.show(); //父类show 子类show!
}
}
/*
* 重写需要遵循“两同两小一大”原则:一般都是一模一样的
* 1.两同:方法名称相同;参数列表相同,不同方法体
* 2.两小:
* 1)子类方法的返回值类型小于或等于父类的
* 1.1)void和基本类型时,必须相同
* 1.2)引用类型时,小于或等于
* 2)子类方法抛出的异常小于或等于父类的-----异常
* 3.一大:子类方法的访问权限大于或等于父类的-----访问修饰符
*/
class Aoo{
void show(){
System.out.println("父类show");
}
}
class Boo extends Aoo{
void show(){
super.show(); //调用父类的show方法
System.out.println("子类show");
}
}
//父类大,子类小
class Coo{
void sayHi() { }
double show() {return 0.0;}
Coo test() {return null;}
Doo say() {return null;}
}
class Doo extends Coo{
void sayHi() { } //void时必须相同
double show() {return 0.0;} //基本类型时必须相同
//int show() {return 0.0;} //编译错误
Doo test() {return null;} //小于父类
//Coo say() {return null;} //编译错误,引用类型时必须小于或等于
}

二、重写和重载的区别
1)重写:父子类中,方法名相同,参数列表相同,不同方法体
遵循“运行期”绑定,根据对象的类型调用方法
2)重载:一个类中,方法名相同,参数列表不同,不同方法体
遵循“编译期”绑定,根据引用的类型绑定方法
public class OverrideDemo {
public static void main(String[] args) {
//重载看引用类型,重写看对象类型
//o的引用类型是Eoo,所以输出父型参数
//o指向的对象类型是Foo,所以o.show()方法走的是Foo类中的方法,输出子类show
Goo goo = new Goo();
Eoo o = new Foo(); //向上造型
goo.test(o); //父型参数 子类show
}
}
class Goo{
void test(Eoo o) { //重载
System.out.println("父型参数");
o.show();
}
void test(Foo o) { //重载
System.out.println("子型参数");
o.show();
}
}
class Eoo{
void show() {
System.out.println("父类show");
}
}
class Foo extends Eoo{
void show() { //重写
System.out.println("子类show");
}
}

三、访问控制
3.1、package
1)作用:避免类的名称冲突
2)建议:包名所有字母都小写
3)类的完全限定名:包.类名
4)包名可以有层次结构,在一个包中可以包含另外一个包
5)创建包名规范
org.apache.commons.lang.StringUtil
StringUtil:类名
lang:模块的名称信息
commons:项目名称信息
org.apache:公司或组织的信息(公司或组织的域名反写)
3.2、import
1)作用:声明类/引入类
2)同包中类可以直接访问,不同包中的类想访问
2.1)先import声明类再访问类(建议),可以用“*”声明该包中所有类的全称
import org.apache.commons.lang.StringUtil
import org.apache.commons.lang.*
2.2)类的全称------太繁琐(不建议)
org.apache.commons.lang.StringUtil S = new org.apache.commons.lang.StringUtil();
3.3、public
公开的,修饰的成员变量和方法可以在任何类中调用
class Aoo{
public int a;
public void show() {}
}
3.4、private
私有的,修饰的成员变量和方法仅仅只能在本类中调用
class Boo{
private int b;
private void print() {}
}
3.5、protected
受保护的,修饰的成员变量和方法可以被子类及同一个包中的类使用
class Coo{
protected int c;
protected void say() {}
}
3.6、默认访问控制符
即不书写任何访问控制符,默认访问控制的成员变量和方法可以被同一个包中的类使用
class Doo{
int d;
void sayHi() {}
}
代码示例:
//类的访问修饰:public和默认的
//类成员的访问修饰:4种都可以用
package oo.day04;
public class Hoo {
public int a; //任何类
protected int b; //本类、子类、同包类
int c; //本类、同包类
private int d; //本类
void show() {
a = 1;
b = 2;
c = 3;
d = 4;
}
}
class Ioo{ //演示private
void show() {
Hoo o = new Hoo();
o.a = 1;
o.b = 2;
o.c = 3;
//o.d = 4; //编译错误
}
}
package oo.day04.vis;
import oo.day04.Hoo;
public class Joo { //同包
void show() {
Hoo o = new Hoo();
o.a = 1;
//o.b = 2; //编译错误
//o.c = 3; //编译错误
//o.d = 4; //编译错误
}
}
class Koo extends Hoo{ //演示protected
void show() {
a = 1;
b = 2;
//c = 3; //编译错误,不同包
//d = 4; //编译错误,不同包
}
}
3.7、访问控制修饰符对比
1)修饰类可以使用public和默认方式
2)public修饰的类可以被任何类使用;默认修饰的类只可以被同一个包中的类使用
3)protected和private可以用于修饰内部类
| 修饰符 | 本类 | 同一个包中类 | 子类 | 其他类 |
|---|---|---|---|---|
| public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
| protected | 可以访问 | 可以访问 | 可以访问 | 不能访问 |
| private | 可以访问 | 可以访问 | 不能访问 | 不能访问 |
| 默认 | 可以访问 | 不能访问 | 不能访问 | 不能访问 |
建议:数据私有化private,行为公开化public
有一个姓名变量age,如果将age定义为public,其它类中可以调用这个age参数,并随意修改;如果将age定义为private,再定义两个方法,一个修改,一个查看,虽然其它类还以可以修改这个age值,但是方法里可以控制修改规则
//创建Person类,定义age变量,即两个方法
public class Person {
private int age;
public void setAge(int age){
if(age<0||age>100){
return;
}
this.age = age;
}
public int getAge(){
return age;
}
}
//创建Person类对象,并调用方法,对age进行修改、查看
public class Test {
public static void main(String[] args) {
Person man = new Person();
man.setAge(300);
System.out.println(man.getAge()); // 0;默认值为0,设置300不符合规则,所以age还是默认值
}
}

四、static:静态的
4.1、静态变量
1)由static修饰
static int b;
2)属于类的变量,存在方法区中,只有一份
3)常常通过类名.来访问static变量
4)何时用:所有对象的数据都一样时使用
//静态变量演示
public class Ooo {
public static void main(String[] args) {
Loo o1 = new Loo();
o1.show(); //结果为a=1,b=1;开始默认都为0,new Loo()时,调用了无参构造,+1
Loo o2 = new Loo();
o2.show(); //结果为a=1,b=2;创建新对象,a在推区重新创建一块内存,b在方法区不动,new Loo()时,a开始默认为0,b为1,在之前被调用过一次
System.out.println(Loo.b); //结果为2,建议通过类名来访问
System.out.println(o1.b); //结构为2,不建议通过引用来访问
}
}
class Loo{
int a;
static int b; //声明静态变量
Loo(){
a++;
b++;
}
void show() {
System.out.println("a="+a);
System.out.println("b="+b);
}
}


4.2、静态方法
1)由static修饰
2)属于类的,存在方法区中,只有一份
3)常常通过类名.来访问
4)没有隐式this传递,静态方法中不能直接访问实例成员
5)何时用:方法的操作仅与参数相关而与对象无关时使用
class Aoo{
int a; //实例变量-----对象点来访问
static int b; //静态变量-----类名点来访问
void show() { //实例方法-----隐式this
this.a++;
Aoo.b++; //默认有个Aoo.
}
static void test() { //静态方法
//a++; //编译错误,没有this就意味着没有对象,而实例成员必须通过对象点来访问,所以静态方法中不能直接访问实例成员
//show(); //编译错误
Aoo.b++; //默认有个Aoo.
}
}
4.3、静态块
1)由static修饰
2)属于类的,类被加载期间自动执行,类只能被加载一次,所以静态块也只能执行一次
3)何时用:常常用户加载/初始化静态资源(图片、音频、视频…)
public class Ooo {
public static void main(String[] args) {
Noo o3 = new Noo(); //输出静态块和构造方法
System.out.println();
Noo o4 = new Noo(); //输出构造方法
}
}
class Noo{
static {
System.out.println("静态块");
}
Noo(){
System.out.println("构造方法");
}
}

4.4、成员变量和静态变量的区别
成员变量(实例变量)
1)属于对象的,存在堆中
2)有几个对象就有几个实例变量
3)必须通过对象名.来访问
静态变量
1)属于类的,存在方法区中
2)只有一份
3)常常用类名.来访问
class Aoo{
int a; //实例变量-----对象点来访问
static int b; //静态变量-----类名点来访问
}
五、final:不能变
5.1、修饰成员变量
修饰成员变量不能被改变。该成员变量需要在初始化时赋值,对象一旦创建即不可改变
/*
* final修饰成员变量,两种方式初始化:
* 1)声明的同时初始化
* 2)构造方法中初始化
* final修饰局部变量,只要在用之前初始化即可
*/
class Ooo{
final int a = 5; //声明的同时初始化
final int b;
Ooo(){
b = 5; //构造方法中初始化
}
void show() {
final int c; //用之前赋值即可,不用可以不赋值
//a = 55; //编译错误,final的变量不能被改变
}
}
5.2、修饰方法
1)修饰方法不能被重写
2)意义:防止子类在定义新方法时造成“不经意”的重写
class Poo{
final void show() { }
void test() { }
}
class Qoo extends Poo{
//void show() { } //编译错误,final的方法不能被重写
void test() { }
}
5.3、修饰类
1)修饰的类不能被继承
2)意义:可以监控滥用继承对系统造成的危害
final class Roo{}
//class Soo extends Roo{} //编译错误,final的类不能被继承
class Too{}
final class Uoo extends Too{} //正确,final的类可以继承别人的