gpt4 book ai didi

java - 如何获取Java中引用的变量类型?

转载 作者:太空宇宙 更新时间:2023-11-04 07:24:27 25 4
gpt4 key购买 nike

我有以下代码。以下是两个问题:

class Parent {  

private void test()
{
System.out.print("test executed!");
}
static void print(){
System.out.println("my class is parent");
}
}

class Child extends Parent
{
static void print(){
System.out.println("my class is Child");
}

}


public class Inheritence {

public static void main(String[] args)
{
Child p1 = new Child();
Parent p = new Child();
System.out.println("The class name of p is "+p.getClass());
System.out.println("The class name of p1 is "+p1.getClass());
System.out.println("p instance of child "+ (p instanceof Child));
System.out.println("p1 instance of child "+ (p1 instanceof Child));
//p.test();
p.print();
}
}


输出为:

The class name of p is class Child
The class name of p1 is class Child
p instance of child true
p1 instance of child true
my class is parent


我以为 p的类名将是 Parent,因为它的类型是 Parent。但是,它打印为 Child。所以我怎么得到 typep

这里的第二个问题是私有方法是否被继承。尽管包括 this在内的许多文章都提到私有方法没有被继承,但在下面的示例中我看到了它是被继承的。以下可能是一些类型转换问题。

class Child1 extends Parent1  
{

}


public class Parent1 {

private void test()
{
System.out.print("test executed!");
}

public static void main(String[] args)
{
Parent1 p = new Child1();
p.test();
Child1 c = new Child1();
//c.test(); The method test from parent1 is not visible
}
}

Output is : test executed!


在这里,我在 test类型为 Child1的对象上调用 Parent1方法。 Child1没有 test方法,因为它没有被继承。但是我仍然得到输出,表明私有方法是继承的!如果 test是受保护的方法,并且我在子类中重写,则尽管被调用的对象类型是parent (parent p1 = new child1());,它还是会被执行的重写方法

编辑:经过几句评论,我使类Parent1和类Child1分开,并新建了一个名为App的类,该类构造了父对象和子对象。现在我无法在下面的代码中调用 p.test

class Child1 extends Parent1  
{


}


class Parent1 {

private void test()
{
System.out.print("test executed!");
} }

public class App1{

public static void main(String[] args)
{
Parent1 p = new Child1();
p.test();//The method test from parent is not visible
Child1 c = new Child1();
//c.test(); //The method test from parent1 is not visible

}
}

最佳答案

解决第二个问题:保持“继承”和“可见性”的概念可能会有所帮助。 private方法m仅在声明该方法的类C内部可见。因此,您完全不能从m外部使用C。此外,即使在C内部,也不能使用x.m(),除非将对象x声明为C类型。但是子类的对象仍然具有方法m,可以调用该方法,但只能在C内部。此示例将进行编译(即使两个类位于单独的文件中):

public class Class1 {
private void test () { System.out.println ("test"); }
public void doThis (Class2 c) {
// c.test(); -- does not compile [1]
((Class1)c).test();
}
}

public class Class2 extends Class1 {
public void doSomething () {
doThis (this);
// ((Class1)this).test(); -- does not compile [2]
}
}


请注意,在 doThis中,即使 test的类型为 c,您仍然可以调用 cClass2方法。但是,您只能这样做是因为代码在声明 Class1方法的类 test()中(这就是[2]不编译的原因);并且只能通过将 c强制转换为 Class1类型的对象(这就是[1]无法编译的原因)来实现。但是,即使在强制转换它以使编译器将其视为类型为 Class1的表达式之后,实际对象仍然具有类型为 Class2的对象。如果要像这样调用覆盖的方法 polymorphic((Class1)c).polymorphic(),它将调用在 Class2中定义的方法,而不是在 Class1中定义的方法,因为该对象实际上仍然是 Class2对象。

因此,我认为从某种意义上说, test是继承的,即使它是私有的。它只是在 Class2中不可见。

更多:我认为了解编译时类型和运行时类型(或实例类型)之间的区别也很有帮助。如果声明变量 Parent x;,则 x的编译时类型为 Parent。如果您的函数 f的返回类型为 Parent,则类似 obj.f(arg,arg2)的表达式的类型将为 Parent。但是在运行时,如果变量或表达式的编译时类型为 Parent,则运行时的实际类型可以为 Parent或其任何子类。运行时类型将基于对象的构造方式。因此,变量可以具有编译时类型 Parent和运行时类型 Child。然后,您只需要知道使用哪种类型以及何时使用。为了检查方法是否可见(在其中使用 private),使用了编译时类型。为了确定子类重写方法时要调用的方法,使用了运行时类型(这就是多态性)。对于 .getClass(),使用运行时类型。无论如何,我就是这样考虑事情的,这样我就不会太困惑。

示例:假设我们有:

class Parent { }
class Child extends Parent { }
class Grandchild extens Child { }


在其他班级,我们有

Parent x1 = new Parent();
Parent x2 = new Child();
Parent x3 = new Grandchild();


变量 x1x2x3的编译时类型均为
Parent。这意味着所有三个变量都可以引用一个实例
ParentChildGrandchild或任何其他实例的
Parent的子类。上面就是这样: x2将引用
Child的实例,而 x3将引用的实例
Grandchild

类似地:

private Parent getAParent(int n) {
if (n == 0) return new Parent();
if (n == 1) return new Child();
if (n == 2) return new Grandchild();
throw new IllegalArgumentException();
}

Parent x4 = getAParent (0);
Parent x5 = getAParent (1);
Parent x6 = getAParent (2);


x5引用 Child的实例, x6引用一个实例
Grandchild

但是所有变量和 getAParent的编译时类型
通话仍为 Parent。编译器不知道哪个类
变量或函数调用实际上是指您运行程序的时间。
因此,如果您在 play()中声明方法 Grandchild,则它们是
仍然非法:

x3.play ();             // ERROR
x6.play (); // ERROR
getAParent(2).play (); // ERROR


因为编译器会考虑两个变量和 getAParent(2)
类型为 Parent,而不是 Grandchild。并且 play没有定义
对于 Parent。要查看这些变量是否具有运行时类型,
具有 play方法将要求编译器生成代码以
在运行时检查,编译器不会这样做。

这就是 p.test()在第二个示例中起作用的原因。即使 p
引用 Child1的实例, p的编译时类型为
Parent1,因为您已将其声明为 Parent1类型。和
编译器认为 Parent1具有 test方法;由于代码
Parent1内部,即使 test方法是可见的
私人的。这就是为什么它起作用。编译器不会生成代码以
检查 p实际引用的运行时类型。希望这可以帮助
解释事情。

关于java - 如何获取Java中引用的变量类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18776099/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com