一、关于Object类中的clone()方法
- Object类中的clone()方法是一个被protected修饰的方法,在Java中所有类的最终父类就是Object,所以在之前的认知中作为Object的子类那么自然是继承了clone()方法的,自然也应该能够调用到clone()方法,但是在实际运用的时候发现了一些与理解的偏差。
- 问题的代码如下
package main.entity.test2;
import main.entity.Person;
public class Test2 {
public static void main(String[] args) {
//在这Person就是一个简单的类
Person p = new Person();
p.clone();//error
}
}
对于protected能访问的范围其实就是本类 同包中的类 还有子类中,实际上对于protected修饰有这么一段描述"对于protected的成员或方法,要分子类和父类是否在同一个包中。与父类不在同一个包中的子类,只能访问自身从父类继承而来的受保护成员,而不能访问父类实例本身的受保护成员"。接下来就以一些示例做说明
二、示例
- 工程结构如下
在这个工程结构中Person为父类、User和Student为子类 区别在于User与Person在同一个包下的同一级,而Student不在
Person代码如下
package main.entity;
public class Person {
public Integer id;
//被protected修饰的成员属性
protected Integer age;
public Person(){
}
protected void testProtected(){
System.out.println("这是一个被protected修饰的方法");
}
}
User代码如下
package main.entity;
public class User extends Person {
}
Student代码如下
package main.entity.test;
public class Student extends Person {
}
当在同一个包中时被protected修饰的成员属性和成员方法是可以访问到的
Test1这个类与Person类在同一个包内 所以可以创建一个Person对象来调用被protected修饰的成员和方法
package main.entity;
public class Test1 {
public static void main(String[] args) {
//Test1这个类与Person类在同一个包内 所以可以创建一个Person对象来调用被protected修饰的成员和方法
Person p = new Person();
System.out.println(p.age);
p.testProtected();
}
}
在同个包内的子类中 除了以父类的对象来访问之外 也能以子类的对象来访问 或者在非静态方法中直接访问
package main.entity;
public class User extends Person {
void test(){
//继承自父类的成员和方法
System.out.println(age);
testProtected();
}
public static void main(String[] args) {
//通过父类的对象实例来访问
Person p = new Person();
System.out.println(p.age);
p.testProtected();
//通过子类自己的实例来访问
User u = new User();
System.out.println(u.age);
u.testProtected();
}
}
所以 在同一个包中时被protected修饰的成员和方法是能通过对象来直接访问到的。
其实也就是只要是在同个包中只要访问方式是合法的那就都能访问到
当在不同的包时
1.不同包并且不是继承类关系:
不同包并且不是继承关系时 直接创建一个对象来访问被protected修饰的成员和方法是访问不到的
package main.entity.test2;
import main.entity.Person;
public class Test2 {
public static void main(String[] args) {
Person p = new Person();
System.out.println(p.age);//error
p.testProtected();//error
}
}
Test2这个类所在的包为main.entity.test2而Person所在的包为main.entity,他们所在的包不是同一个所以不能访问
所以类似的 你也不能这么写
package main.entity.test2;
public class Test2{
public static void main(String[] args) {
Object obj = new Object();//error
obj.clone();//error
}
}
因为Object所在的包为java.lang和Test2所在的包不是同一个
不同包但是有继承关系
package main.entity.test;
import main.entity.Person;
public class Student extends Person {
void test(){
//子类继承的受保护的成员
testProtected();
System.out.println(age);
//父类的实例对象
Person person = new Person();
person.testProtected(); //error
person.age; //error
//子类的实例对象
Student student = new Student();
System.out.println(student.age);
student.testProtected();
}
}
这里
Person person = new Person();
person.testProtected(); //error
person.age; //error
这个写法也是错误的,这不是在子类中了吗为什么还是错误的
接下来就要解释与父类不在同一个包中的子类,只能访问自身从父类继承而来的受保护成员,而不能访问父类实例本身的受保护成员这句话
1.只能访问自身从父类继承而来的受保护成员
就是只能通过子类自己的对象来访问从父类继承而来的受保护成员
Student类从Person类继承了的受保护的成员有protected Integer age和protected void testProtected(),所以在Student 类里能够通过Student的对象访问到这两个成员如上面的代码所示
2.不能访问父类实例本身的受保护成员
不能用父类的对象来访问父类的受保护成员
父类的实例即为 Person person = new Person();所创建的person对象,访问的是父类实例本身的testProtected()方法和age属性而不是子类的,属于在不同的包中进行访问了,所以即使是在子类中也不能这样来访问。
Person person = new Person();
person.testProtected(); //error
person.age; //error
但是可以在子类中这样访问
Student student = new Student();
System.out.println(student.age);
student.testProtected();
总结的说:
1.如果在被protected所修饰的属性或者方法所在的类中或者在同一个包下只要是合法的访问方式都可以访问到
3.如果与被protected所修饰的属性或者方法所在的类不同包但是有继承关系,则只能在子类中通过子类的对象实例来访问
我们回归最开始所说的Person类为什么不能在Test2中调用clone()方法
1.Object类所在的包为java.lang包,Person所在的包为main.entity
2.clone()方法来自父类Object类
3.Person类是Object类的子类
所以Person类与Object类是属于不在同一个包下的父子类的关系,想要调用受保护的方法或者属性只能在子类(Person类)中用子类(Person)的对象进行调用,其他的调用方式都是错误的。