我是Java新手,我读过线程(here),无法实例化抽象类。所以,我测试了它。
我做的第一个测试如下所示。似乎我实际上可以实例化一个抽象类,实际上,我实际上有一个新的类型,它引用了抽象类,并且实际上所有子类都共享了类型。这也意味着多态性适用。
import java.util.*;
abstract class AbstractClass{
public abstract void printname();
}
class Test1 extends AbstractClass{
private String name;
public Test1(String name){
this.name = name;
}
public void printname(){
System.out.println("My name is " + name);
}
}
class Test2 extends AbstractClass{
private String saysomething;
public Test2(String saysomething){
this.saysomething = saysomething;
}
public void printname(){
System.out.println(saysomething);
}
}
class TestingApp{
public static void main(String[] args){
AbstractClass[] abstractclass_list = {new Test1("JEFFFFFF") , new Test2("Hey , say something")};
for(AbstractClass item : abstractclass_list){
item.printname();
}
}
}
然后我做了另一个测试,但这一次,我决定创建一个引用Interface的类型,而不是在抽象类上工作。看起来我也可以实例化一个接口。我实际上可以创建一个引用接口的类型。实现此接口的所有类共享此类型。并且多态性再次适用。
import java.util.*;
interface AbstractInterface{
public void printname();
}
class Test4 implements AbstractInterface{
private String name;
public Test4(String name){
this.name = name;
}
public void printname(){
System.out.println("My name is " + name);
}
}
class Test3 implements AbstractInterface{
private String saysomething;
public Test3(String saysomething){
this.saysomething = saysomething;
}
public void printname(){
System.out.println(saysomething);
}
}
class TestingAbstractInterfaceApp{
public static void main(String[] args){
AbstractInterface[] abstract_list = {new Test4("Helen") , new Test3("Hey , say my name")};
for(AbstractInterface item : abstract_list){
item.printname();
}
}
}
问题:
我感觉我在代码中所做的事情有问题。但是我无法解释为什么代码在理论上仍然有效,不可能实例化一个抽象类和接口。我实际上是在上面显示的示例中实例化一个抽象类和一个接口吗?因为这看起来就像我所做的那样,因为我有一个抽象类和接口的新类型。如果我的逻辑错误或我使用了错误的词语,请纠正我。
更新 所以我想我的误解是关于类型。我一直认为type只能引用普通的Java类,而不能引用抽象的类和接口。怎么"键入"实际上工作?它是否正在创建参考?
答案 0 :(得分:3)
为什么您认为实际上是在实例化AbstractClass
和AbstractInterface
?
new Test1("JEFFFFFF") , new Test2("Hey , say something"), new Test4("Helen") , new Test3("Hey , say my name")
都是实例化的具体类,而不是抽象类。
如果您将AbstractClass[] abstractclass_list =
称为实例化抽象类的证据,那就错了。在这里,您声明一个数组类型为AbstractClass
,Test1
和Test2
的数组(因为它们extend AbstractClass
)。
<强>更新强>
你可以拥有类似AbstractClass abs = new Test1("hey");
之类的东西,它的作用是创建一个新的类Test1
实例,并从变量abs
引用该实例。 abs
的具体类型为Test1
,但只有AbstractClass
中声明的方法才可见。如果您想调用Test1
的方法,则必须先将其强制转换。
AbstractClass abs = new Test1("hey");
abs.printname(); // this is ok, and it calls `printname() implemented in Test1
abs.someTest1Method(); // this is NOT ok, someTest1Method() is not visible to abs
((Test1)abs).someTest1Method(); // this is ok, abs is cast to Test1, but would fail if abs was instantiated as 'abs = new Test2("t2")' (would throw ClassCastException)
答案 1 :(得分:1)
您没有实例化您的抽象类或您的界面。您正在实例化扩展抽象类(Test1
和Test2
)的具体类,或实现您的接口(Test3
和Test4
)。
允许将具体类的实例分配给类型为接口或抽象类的变量。事实上,它甚至受到了鼓励。
答案 2 :(得分:1)
您既不是实例化抽象类,也不是实例。您只是使用从子类到超类的固有向上转换功能。
忽略数组,只使用第一个对象,这相当于隐式的upcast:
AbstractClass myObject = new Test1("JEFFFFFF");
和
AbstractInterface myObject = new Test1("JEFFFFFF");
所以,在代码中:
AbstractClass[] abstractclass_list = {
new Test1("JEFFFFFF") ,
new Test2("Hey , say something")};
您正在实例化具体类Test1
和Test2
的对象 - Array包含对底层(和公共)抽象基类的引用。
同样,在第二个示例中,您将获得一个接口引用数组。
答案 3 :(得分:1)
总之我想说的是,
Parent(here, Abstract/Iterface)
可以引用,child(here, concrete class)
。
所以在这里,引用变量可以引用它的子类的实例。
在你的大脑中注意这个概念,它将解决你所有的问题,动态调度程序,继承相关...... !!!
答案 4 :(得分:0)
您不是instantiating
abstract
班级和interface
,
您instantiating
类implementations
和abstract
类interface
AbstractClass
。
如果声明AbstractInterface
或{{1}}的列表,则可以只调用在超类或接口上声明的方法,但不能调用在特定实现(Test1,Test2,Test3和Test4)上声明的方法。< / p>