当前位置: 技术问答>java相关
protected和static关键字的疑惑!
来源: 互联网 发布时间:2015-07-28
本文导语: 1.在Java2 认证考试指南(机械工业出版社 原书第三版)中如是描述: protected修饰符使得类的变量、方法、构造器可以被同包中的类或者接口所访问,也可以被所在类的子类(理所当然在其他包的子类也可以)所访问。 ...
1.在Java2 认证考试指南(机械工业出版社 原书第三版)中如是描述:
protected修饰符使得类的变量、方法、构造器可以被同包中的类或者接口所访问,也可以被所在类的子类(理所当然在其他包的子类也可以)所访问。
2.而在Beginning Java 2(电力出版社)中,类成员访问属性描述那章也是上面这样说的。可是在继承那章却有如下的话:“protected限制包以外的类对其进行访问,但是不限制继承。没有访问修饰符的成员限制在同一包内可以访问,而且阻止包外面的子类继承”,这真是让人迷惑,感觉protected可以阻止包外的子类访问(分明更多的书上不是这样讲的),而可以继承。但究竟是这样的么?
我做了如下测试,得到的结果更是奇怪。希望高人能解释一下:
文件Tree.java描述基类test.Tree:
package test;
public class Tree
{
protected int age=2;
protected void outPut()
{
System.out.println("Inherit Test!");
}
}
用javac -d . Tree.java编译通过。class肯定在classpath中。
Pine.java描述子类Pine(使用默认包,以达到和父类不同包的效果)
public class Pine extends test.Tree
{
public static void main(String[] args)
{
test.Tree tmp = new test.Tree();
tmp.outPut();
System.out.println(tmp.age);
}
}
结果编译出错:
D:workjavatestPine.java:13: outPut() has protected access in test.Tree
tmp.outPut();
^
D:workjavatestPine.java:14: age has protected access in test.Tree
System.out.println(tmp.age);
^
2 errors
而如果将protected改为public或者将Pine、Tree置于同一包中时,均可正常运行通过。
而由此,我认为开始的观点2的确是正确的。也就是说:protected限制包以外的类对其进行访问!!!这真是让人吃惊。不过我很快意识到这种想法可能还是错的。因为也许(我还是不能肯定)不能靠新生成一个父类的实例来实现对父类(不同包)的protected的成员(fields)和方法的访问,而要靠super这个关键字。
将Pine.java做了如下修改后变异运行通过:
public class Pine extends test.Tree
{
public static void main(String[] args)
{
test.Tree tmp = new test.Tree();
//tmp.outPut(); 这样会出错。说什么outPut()是protected。不过至今不解为啥
Pine pine = new Pine();
pine.access();
//System.out.println(tmp.age);//同样的错误。
}
private void access(){
super.outPut();
System.out.println("And also accesses 'age': "+super.age+" Successfully!");//这样就行。真有些想不通。
}
}
但很偶然的我将test.Tree修改为:
package test;
public class Tree
{
protected static int age=2; //修改为静态变量;
protected static void outPut() //修改为静态方法;
{
System.out.println("Inherit Test!");
}
}
重新编译后,结果居然老的Pine.java(也就是靠临时生成一个父类的实例来访问父类的protected成员和方法)也能编译了,也能运行了。
因此实在是不解啊。高人指点?
另外Java 2认证考试指南说static的方法是不能被子类覆盖的,但我做了测试这分明是行的啊(肯定不是类似于对父类private同名方法重建的,因为要求返回值一样)。当然和abstract一起使用还是不行的。在此也向各位求证一下到底该怎么说啊?
或者能提供的Java程序员认证经验的人均给分!
protected修饰符使得类的变量、方法、构造器可以被同包中的类或者接口所访问,也可以被所在类的子类(理所当然在其他包的子类也可以)所访问。
2.而在Beginning Java 2(电力出版社)中,类成员访问属性描述那章也是上面这样说的。可是在继承那章却有如下的话:“protected限制包以外的类对其进行访问,但是不限制继承。没有访问修饰符的成员限制在同一包内可以访问,而且阻止包外面的子类继承”,这真是让人迷惑,感觉protected可以阻止包外的子类访问(分明更多的书上不是这样讲的),而可以继承。但究竟是这样的么?
我做了如下测试,得到的结果更是奇怪。希望高人能解释一下:
文件Tree.java描述基类test.Tree:
package test;
public class Tree
{
protected int age=2;
protected void outPut()
{
System.out.println("Inherit Test!");
}
}
用javac -d . Tree.java编译通过。class肯定在classpath中。
Pine.java描述子类Pine(使用默认包,以达到和父类不同包的效果)
public class Pine extends test.Tree
{
public static void main(String[] args)
{
test.Tree tmp = new test.Tree();
tmp.outPut();
System.out.println(tmp.age);
}
}
结果编译出错:
D:workjavatestPine.java:13: outPut() has protected access in test.Tree
tmp.outPut();
^
D:workjavatestPine.java:14: age has protected access in test.Tree
System.out.println(tmp.age);
^
2 errors
而如果将protected改为public或者将Pine、Tree置于同一包中时,均可正常运行通过。
而由此,我认为开始的观点2的确是正确的。也就是说:protected限制包以外的类对其进行访问!!!这真是让人吃惊。不过我很快意识到这种想法可能还是错的。因为也许(我还是不能肯定)不能靠新生成一个父类的实例来实现对父类(不同包)的protected的成员(fields)和方法的访问,而要靠super这个关键字。
将Pine.java做了如下修改后变异运行通过:
public class Pine extends test.Tree
{
public static void main(String[] args)
{
test.Tree tmp = new test.Tree();
//tmp.outPut(); 这样会出错。说什么outPut()是protected。不过至今不解为啥
Pine pine = new Pine();
pine.access();
//System.out.println(tmp.age);//同样的错误。
}
private void access(){
super.outPut();
System.out.println("And also accesses 'age': "+super.age+" Successfully!");//这样就行。真有些想不通。
}
}
但很偶然的我将test.Tree修改为:
package test;
public class Tree
{
protected static int age=2; //修改为静态变量;
protected static void outPut() //修改为静态方法;
{
System.out.println("Inherit Test!");
}
}
重新编译后,结果居然老的Pine.java(也就是靠临时生成一个父类的实例来访问父类的protected成员和方法)也能编译了,也能运行了。
因此实在是不解啊。高人指点?
另外Java 2认证考试指南说static的方法是不能被子类覆盖的,但我做了测试这分明是行的啊(肯定不是类似于对父类private同名方法重建的,因为要求返回值一样)。当然和abstract一起使用还是不行的。在此也向各位求证一下到底该怎么说啊?
或者能提供的Java程序员认证经验的人均给分!
|
1, test.Tree tmp = new test.Tree(),然后用tmp引用来访问test.Tree的方法这已经不是对基类的访问了,可称为对test.Tree类对象的方法调用(虽然你extends test.Tree),和其他类用test.Tree tmp = new test.Tree()没有区别,用super.xxx才是对基类的访问方式。
2, 至于你将变量和方法改为static后,能用test.Tree tmp = new test.Tree(),的tmp引用访问,这种情况实际上就绕开了“可称为对test.Tree类对象的方法调用“,tmp.age能通过与你实例化test.Tree无关,不用new xxx一样行,只要有这句:test.Tree tmp,而age是一个静态字段,不实例化同样存在。
方法outPut()同理。
2, 至于你将变量和方法改为static后,能用test.Tree tmp = new test.Tree(),的tmp引用访问,这种情况实际上就绕开了“可称为对test.Tree类对象的方法调用“,tmp.age能通过与你实例化test.Tree无关,不用new xxx一样行,只要有这句:test.Tree tmp,而age是一个静态字段,不实例化同样存在。
方法outPut()同理。
|
一. 修饰符
类变量(对象共享) 类名,对象名点取
类方法 1)static方法中不能直接使用非静态成员, 因
为非静态成员与实例相关,通过对象点取间接使用
2)static方法中不能用this(与实例相关)
3)非static方法中可以使用static成员
static块:和数据成员时并列的位置,用于类初始化
类装入时执行一次(第一次创建对象,第一次使用
static成员,不同的静态块,按在类中的顺序执行)
注:只能修饰成员,不能修饰方法变量.
static方法覆盖时,没有起到覆盖的作用
类变量(对象共享) 类名,对象名点取
类方法 1)static方法中不能直接使用非静态成员, 因
为非静态成员与实例相关,通过对象点取间接使用
2)static方法中不能用this(与实例相关)
3)非static方法中可以使用static成员
static块:和数据成员时并列的位置,用于类初始化
类装入时执行一次(第一次创建对象,第一次使用
static成员,不同的静态块,按在类中的顺序执行)
注:只能修饰成员,不能修饰方法变量.
static方法覆盖时,没有起到覆盖的作用
|
protected修饰符修饰的变量、方法,限制包以外的类对其进行访问。
就是说,在一个类中不能调用其他类的protected变量和方法,要想调用,
必须是public。
关于继承,子类会继承其父类的protected、public变量和方法
所以用super.xx就没问题,因为该方法是他继承父类的成员方法
就是说,在一个类中不能调用其他类的protected变量和方法,要想调用,
必须是public。
关于继承,子类会继承其父类的protected、public变量和方法
所以用super.xx就没问题,因为该方法是他继承父类的成员方法
|
你提供的例子:
public class Pine extends test.Tree
{
public static void main(String[] args)
{
test.Tree tmp = new test.Tree();
tmp.outPut();
System.out.println(tmp.age);
}
}
中,你是在Pine中调用Tree的outPut方法,protected限制派生类以外的调用,是指派生类(Pine)可以调用父类(Tree)的protected方法,而不是在派生类中可以用父类(Tree)调用父类本身(Tree)的方法,二你的程序是后者,所以不行。可以改为:
test.Pine tmp = new test.Pine();//派生类
tmp.outPut();//调用父类的保护方法
希望队你有所帮助
public class Pine extends test.Tree
{
public static void main(String[] args)
{
test.Tree tmp = new test.Tree();
tmp.outPut();
System.out.println(tmp.age);
}
}
中,你是在Pine中调用Tree的outPut方法,protected限制派生类以外的调用,是指派生类(Pine)可以调用父类(Tree)的protected方法,而不是在派生类中可以用父类(Tree)调用父类本身(Tree)的方法,二你的程序是后者,所以不行。可以改为:
test.Pine tmp = new test.Pine();//派生类
tmp.outPut();//调用父类的保护方法
希望队你有所帮助
|
楼上的解释的很清楚,至于你说的在变量前加上static关键字,第一个程序就可以编译运行了,那是绝对不可能的.一个变量能否被访问只与访问修饰符public,protected,private和友好的(就是什么也不加)有关,与是否是static是无关的.好好看看Thing in java对你会有帮助的!
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。