构造方法
构造方法是一个与类同名的方法,它主要完成对象的初始化,当该类实例化一个对象时会自动调用构造方法.一个类中必须含有构造方法,但并非强制要求写出,如果没有写出的话Java会自动添加一个无参构造方法以供初始化,该构造方法不包含任何的参数,且方法体为空.
默认构造方法的访问修饰符将会和所在类的访问修饰符保持一致,一旦我们在程序中定义了构造方法,那么该默认方法将会失效.
要调用构造方法,应在创建对象时使用new
关键字:
public class Test{
public Test() {
}
public static void main(String[] args){
Test x = new Test();
}
}
值得注意的是,构造方法不允许被static
/final
/native
等关键字进行修饰,也没有返回值,且不允许被void修饰,但在使用new关键字调用构造方法的上述实例中,此时构造方法会返回当前类.
构造方法会在初始化对象的过程中被自动执行,一般情况下不能够被直接调用.
构造方法具有无参和有参两种形式,在一个类中允许定义多个同名方法,前提是这些方法的参数列表不能够相同,在运行时Java编译器会根据方法签名(参数类型)来判断要调用哪一个方法,这种行为被称为方法的重载,值得注意的是重载必须使参数列表相异,仅仅使访问修饰符或是访问类型不同来重载方法使错误的.
public class Test{
//无参构造方法
public Test(){
}
//有参构造方法
public Test(int x){
}
//重载方法
public Test(double m, int n){
}
}
静态与非静态
在类中使用static进行修饰的方法被称为静态方法,而此外的方法则被统称非静态方法.
类的静态方法在载入类的同时载入的,会随着定义类被装载入内存.
静态方法既能够被静态方法访问,也能够被非静态方法访问;但非静态方法不可被静态方法访问.静态方法在调用时不需要实例化相应的对象,能够通过类名直接调用,而非静态方法依赖于特定对象,因此在调用它们时需要进行对象的创建.以下是一个简单示例 :
public class Test{
public static int a;
public int b;
// '静态'对象无法访问'非静态'数据
static{
a = 1;
// b = 2; *报错 - 无法从 static 上下文引用非 static 字段 'b'
}
//'静态'对象无法访问'非静态'数据
public static int getA(){
return a;
// return b; *报错 - 无法从 static 上下文引用非 static 字段 'b'
}
// '非静态'对象可以访问'静态'数据
public int getB(){
return a;
}
// '非静态'对象可以访问'非静态'数据
public int getC(){
getB();//'非静态'方法可以调用'非静态'方法
b = a;
return b;
}
}
包(Package)的访问级别控制
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。
来自 Runoob.com
包有着与文件目录类似的树形储存方式,同一个包中不允许存在相同的类名,但不同包中没有对类名的严格限制,在有同名的类要进行使用时加上包名以倒置域名的形式进行调用,譬如com.test.testclass
,包的多层结构名之间以.
加以分隔.
包亦允许通过访问权限修饰符进行限定范围:
修饰符 | 本类-Class | 同包-Package | 子类(非同包)-Subclass | 非子类(非同包)-World |
---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
默认 | ✔️ | ✔️ | ❌ | ❌ |
在未加上访问控制修饰符(也称为 package-private
)的默认访问级别(Friendly
)中,当前类中的方法只能被同一个包中的其它类调用,而不能被其他包中的任何类进行调用,如果要直接调用则需要给包加上public进行修饰.
值得注意的是,protected
修饰的方法不能被直接调用,需要进行继承通过子类的对象调用继承而来的方法,子类可以直接访问父类中的非private
的属性和行为.
关于继承的简单实例:
class Test{}
class subTest extends Test{} //SubTest为子类,Test为被继承的父类.
class extraTest extends subTest{} //类的多重继承
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
多个类可以称为子类,单独这个类称为父类、超类或者基类.子类可以直接访问父类中的非私有的属性和行为。
通过
extends
关键字让类与类之间产生继承关系。来自 Runoob.com
❗只有在两个类之间为完全相等的关系时才考虑使用继承,而不是仅仅为了继承一部分功能使用继承.
方法重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
在面向对象原则里,重写意味着可以重写任何现有方法。
来自 Runoob.com
在继承了一个类之后,如果想要调用这个类中的方法,那么就可以使用重写来实现
假设有这样一种情况,我们在类文件testOverride.class
之中定义了一个类,其中有一个方法,恰好有另一个类文件Test.class
想要调用testOverride.class
中的这个方法,这时会发现直接使用Class.Method
的形式用不了了.
public class testOverride{
public int value(){
int a = 6;
return a;
}
}
那么可以先写一个工具类用来作为方法的中转站,先使用extends
关键字进行继承,然后打上一个@Override
标签提醒我们这是重写的方法,然后直接使用super
关键字调用返回值给重写类,就可以把这个值传递到新的类中使用了.
public class Test{
public static class toolMethod extends testOverride{
@Override
public int value(){
return super.value();
}
}
}
在Test类中如果要调用重写过来的新的方法,必须要先创建一个该类的实例对象,再通过这个对象进行引用.
public class Test{
toolMethod tm = new toolMethod();
int num = tm.value();
System.out.println(num);
public static class toolMethod extends testOverride{
@Override
public int value(){
return super.value();
}
}
}
方法的重写还有许多规则,首先是被重写方法的参数列表必须与原方法完全相同,其次包与重写权限的关系遵循访问修饰符的权限级别且不能越级,private > friendly > protected > public
,即父类的权限级别不可小于子类.注意,构造方法不能被重写.
参考文章:
https://blog.csdn.net/qq_39098813/article/details/80341896
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
https://www.runoob.com/w3cnote/java-extends.html
https://www.runoob.com/java/java-package.html
https://www.runoob.com/java/java-methods.html
https://www.runoob.com/java/java-override-overload.html