Java抽象类可以被实例化吗

发布于 2022-01-01 15:58:39 字数 63 浏览 429 评论 5

只有new的对象才算实例化吗?什么才算实例化呢!子类继承抽象父类的时候会执行父类的无惨的构造方法,这个算实例化吗

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无声静候 2022-01-08 06:02:46

假如是一个抽象类,拥有实现的子类的话,可以使用 父类  实例名=new 子类()实例化,但是这种实际上也是利用子类new出父类 ,没有子类的话抽象类是不能实例化的

甜扑 2022-01-08 03:16:35

Java的抽象类 和它的实体

    抽象,就是从许多具体事物中舍弃个别的、特殊的属性,抽出共同的、本质的属性。

    定义任何类,若在关键词class 之前加上修饰符 abstract,它就成了抽象类。抽象类不允许直接被实例化。就是说,在任何一个能实例化的类的定义前,放上关键字 abstract ,给定类就被看作是抽象类,进而不能直接被实例化了。显然/尽管,这种抽象类中没有抽象的方法。常见的情况是,在定义一个类的时候, 一旦出现了抽象方法,这个类就是抽象的, 必须在关键字class之前放上修饰符 abstract ,否则会有编译错误。

    定义抽象方法的必要性:比如,定义类 Person的时候,各种人的吃饭方式各有不同:中国人用筷子吃饭, 西方人用刀叉吃饭, 或印度人用手抓着吃饭。 因此,定义吃饭方法 havingDinner()的时候,就要从多种人中舍弃个别的、具体的操作(如用筷子吃饭, 用刀叉吃饭, 或用手抓着吃饭),抽出共同的、本质的操作:吃饭, 产生了抽象方法 havingDinner()。 做法是,忽略方法体(即不包括一对花括号和其中的代码块)而仅给出方法的签名。就是说,只有方法的特征没有方法的实现,以构成抽象方法。

    正是因为有了这一个抽象方法:吃饭, 所以 Person 就必须是抽象类,即在类定义之前必须冠以 abstract class Person, 以示它为 抽象类, 不可直接使用 new 操作符来创建实体。

    然而,抽象类 Person 可以有实体。它可以通过它的子类(派生类)产生它的对象。所以,可以这样回答楼主的提问:"Java抽象类可以被实例化吗?"  Java抽象类不可以直接 借助 操作符 new 被实例化,但它可以 通过完善了它的抽象方法定义的子类(派生类),借助 操作符 new ,产生它 (Person) 的对象。这种案例,被称作"向上转型 Upcasting"。其优点是,可以将多种不同子类对象的引用,储存于单一种类 (抽象类/父类 Person) 的 引用之中。案例见如下代码。

    从这个案例也可见,在抽象类 Person 的定义之中, 定义一个静态的方法 getInstane(), 调用它也可以返回一个 Person 类的对象。表面上,似乎借用抽象类 Person 的名字来调用它的静态方法,也可以实例化抽象类 Person。但进一步追究这个方法的定义就会发现,它仍然要使用 操作符 new 和一个匿名(子)类来达到实例化抽象类 Person 的目的。  

/*因为类的定义中有一个抽象方法:吃饭, 
* 所以它必须是抽象类
*/
abstract class Person { 
	protected String name;
	public Person(String name){
	this.name=name;
 	}
/* 不同人吃饭方法不一样,放在一起定义太麻烦,
 * 或不可能,因此只能冠以修饰符 abstract,
 * 随后给出方法的签名
 */
	abstract String havingDinner();
	
	static Person getInstane(){
		return new Person("Noname"){
			String havingDinner(){
				return name + " is using unknown manner to eat. 无名氏用未知方式吃饭。";
			}
		};
	}
}

class Chinese extends Person{ // 具体定义中国人
	public Chinese(String name){
		super(name);
	}
	public String havingDinner(){ //吃饭具体化
		return name + "用筷子吃饭。";
	}
}
class American extends Person{ // 具体定义美国人
	public American(String name){
		super(name);
	}
	public String havingDinner(){ //吃饭具体化
		return name + "用刀叉吃饭。";
	}
}
class Indian extends Person{ //具体定义印度人
	public Indian(String name){
		super(name);
	}
	public String havingDinner(){ //吃饭具体化
		return name + "用手抓着吃饭。";
	}
}

public class AbstractTest {
	public static void main(String args[]){
	Person p[]=new Person[4];
	p[0] = new Chinese("李明");
	p[1] = new American("特朗普");
	p[2] = new Indian("桑贾伊·甘地");
	p[3] = Person.getInstane();
	for (Person r:p)
	System.out.println(r.havingDinner());
	}
}

输出:

李明用筷子吃饭。
特朗普用刀叉吃饭。
桑贾伊·甘地用手抓着吃饭。
Noname is using unknown manner to eat. 无名氏用未知方式吃饭。

 

顺便提一点: "向上转型 Upcasting" 一般都可行,因为,无论中国人、美国人、还是印度人,他/她们都是人。然而,"向下转型 Downcasting",即 将 Person 类型的引用,强制转换成其子类的引用,是有条件的。条件是:Person 的引用,必须是调用这个给定的子类的构造方法而创建的。这是因为:一个人不一定就是 中国人、美国人、或是印度人。  

参考:
看深入jvm遇到的问题,为什么输出是外部类的方法结果

睫毛上残留的泪 2022-01-07 15:38:43

是否可以再考虑一下你的第二句话,它可能不全面。 子类调用父类构造器之后,也可能就创建完了一个对象,完成实例化。 楼下的代码案例表明:子类的构造器,仅仅调用了父类的构造器就可以完成实例化。这是因为,子类没有添加任何需要初始化(赋值)的属性。

风柔一江水 2022-01-07 04:09:11

回复
@tcxu : 抠字眼的话,完整的表述应该是:子类调用父类构造器的时候还并未创建完这个子类的对象。反而,“可能创建完了一个对象”这种表述才更加要避免。子类的构造器中调用了父类构造器,如果这个构造方法还未结束,就还没有完成这个对象的实例化,而且也无法将其返回使用,这个对象尚处于实例化中。当然,这是个概念问题,没多少意义。

画骨成沙 2022-01-04 16:16:12

实例化就是创建一个对象,new对象是最常用的实例化的途径。

子类调用父类构造器的时候还并未创建完一个对象,所以实例化尚未完成。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文