Student.java
class Person
{
public int age;
public String name;
public Person(int age,String name){
this.setAge(age);
this.setName(name);
}
public void info(){
System.out.println("sdflksdj");
}
public void setAge(int age){
this.age=age;
}
public void setName(String name){
this.name=name;
}
public int getAge(){
return this.age;
}
public String getName(){
return this.name;
}
}
public class Student extends Person
{
public String school;
public Student(int age,String name,String school){
super(age,name);
this.setSchool(school);
}
public void setSchool(String school){
this.school=school;
}
public String getSchool(){
return this.school;
}
}
编译:javac Student.java
分析字节码:javap -c -private Student.java
Compiled from "Student.java"
public class Student extends Person {
public java.lang.String school; public Student(int, java.lang.String, java.lang.String);
Code:
0: aload_0
1: iload_1
2: aload_2
3: invokespecial #1 // Method Person."<init>":(ILjava/la
ng/String;)V
6: aload_0
7: aload_3
8: invokevirtual #2 // Method setSchool:(Ljava/lang/Stri
ng;)V
11: return public void setSchool(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #3 // Field school:Ljava/lang/String;
5: return public java.lang.String getSchool();
Code:
0: aload_0
1: getfield #3 // Field school:Ljava/lang/String;
4: areturn public java.lang.String getName();
Code:
0: aload_0
1: invokespecial #4 // Method Person.getName:()Ljava/lan
g/String;
4: areturn public int getAge();
Code:
0: aload_0
1: invokespecial #5 // Method Person.getAge:()I
4: ireturn public void setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: invokespecial #6 // Method Person.setName:(Ljava/lang
/String;)V
5: return public void setAge(int);
Code:
0: aload_0
1: iload_1
2: invokespecial #7 // Method Person.setAge:(I)V
5: return public void info();
Code:
0: aload_0
1: invokespecial #8 // Method Person.info:()V
4: return
}
如果我把声明Studnet类的的public去掉
编译:javac Student.java 通过
分析字节码:javap -c -private Student
则:
Compiled from "Student.java"
class Student extends Person {
public java.lang.String school; public Student(int, java.lang.String, java.lang.String);
Code:
0: aload_0
1: iload_1
2: aload_2
3: invokespecial #1 // Method Person."<init>":(ILjava/la
ng/String;)V
6: aload_0
7: aload_3
8: invokevirtual #2 // Method setSchool:(Ljava/lang/Stri
ng;)V
11: return public void setSchool(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #3 // Field school:Ljava/lang/String;
5: return public java.lang.String getSchool();
Code:
0: aload_0
1: getfield #3 // Field school:Ljava/lang/String;
4: areturn
}就去掉了一个public,怎么会有这样的区别????
很是纳闷,去掉public后,从分析的字节码来看,好像Studnet类没有继承Person类(当然是继承了)
但是没去掉public之前,明显看出是继承了Person类,希望能从根本上给解答一下。
{
public int age;
public String name;
public Person(int age,String name){
this.setAge(age);
this.setName(name);
}
public void info(){
System.out.println("sdflksdj");
}
public void setAge(int age){
this.age=age;
}
public void setName(String name){
this.name=name;
}
public int getAge(){
return this.age;
}
public String getName(){
return this.name;
}
}
class Student extends Person
{
public String school;
public Student(int age,String name,String school){
super(age,name);
this.setSchool(school);
}
public void setSchool(String school){
this.school=school;
}
public String getSchool(){
return this.school;
}
}
Compiled from "Student.java"
public class Student extends Person {
public java.lang.String school; public Student(int, java.lang.String, java.lang.String);
Code:
0: aload_0
1: iload_1
2: aload_2
3: invokespecial #1 // Method Person."<init>":(ILjava/
ng/String;)V
6: aload_0
7: aload_3
8: invokevirtual #2 // Method setSchool:(Ljava/lang/St
ng;)V
11: return public void setSchool(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #3 // Field school:Ljava/lang/String;
5: return public java.lang.String getSchool();
Code:
0: aload_0
1: getfield #3 // Field school:Ljava/lang/String;
4: areturn public java.lang.String getName();
Code:
0: aload_0
1: invokespecial #4 // Method Person.getName:()Ljava/l
g/String;
4: areturn public int getAge();
Code:
0: aload_0
1: invokespecial #5 // Method Person.getAge:()I
4: ireturn public void setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: invokespecial #6 // Method Person.setName:(Ljava/la
/String;)V
5: return public void setAge(int);
Code:
0: aload_0
1: iload_1
2: invokespecial #7 // Method Person.setAge:(I)V
5: return public void info();
Code:
0: aload_0
1: invokespecial #8 // Method Person.info:()V
4: return
}
用javap -c -private再次分析
javap -c -private StudentCompiled from "Student.java"
class Student extends Person {
public java.lang.String school; public Student(int, java.lang.String, java.lang.String);
Code:
0: aload_0
1: iload_1
2: aload_2
3: invokespecial #1 // Method Person."<init>":(ILjava/la
ng/String;)V
6: aload_0
7: aload_3
8: invokevirtual #2 // Method setSchool:(Ljava/lang/Stri
ng;)V
11: return public void setSchool(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #3 // Field school:Ljava/lang/String;
5: return public java.lang.String getSchool();
Code:
0: aload_0
1: getfield #3 // Field school:Ljava/lang/String;
4: areturn
}
试试
我的意思是说对于Student.java文件,去掉Student类前的public前后用javap分析一下出来的结果不一样,去掉后,父类的方法没有在子类中体现,我是这个意思,这个什么原因呢
Person类的访问修饰为默认访问(即包内可见,等同于C++的访问修饰符friendly,由于在下的习惯问题,下面提到的friendly都是指Java的默认访问)。由于Person类本身是friendly的缘故,其定义的函数info等虽然修饰符为public,但实际的可见范围也是friendly。这时用一public的类Student去继承Person类,无意中扩大了info等函数的可见范围。因此在Student类的代码中要包含可见范围被扩大的info等函数的代码。1、将Student类也定义为friendly
2、将Person类定义为public
3、将info等函数定义为friendly或可见范围更小的private
以上三种情况都不会造成函数可见范围扩大,子类Student中也不必包含父类Person中定义的函数代码了。