为什么不';t类是Java中的第一类对象吗?
有人能给我解释一下为什么类不是Java中的第一类对象吗?如果有,某些模式会很好地工作,我一直在用getter和setter编写工厂类,只是在类中添加了不必要的cruft,这样我就可以把实例传递给方法,而不是实际的类,从而分解出通用的代码位。例如:为什么不';t类是Java中的第一类对象吗?,java,generics,Java,Generics,有人能给我解释一下为什么类不是Java中的第一类对象吗?如果有,某些模式会很好地工作,我一直在用getter和setter编写工厂类,只是在类中添加了不必要的cruft,这样我就可以把实例传递给方法,而不是实际的类,从而分解出通用的代码位。例如: public class AsyncBookSearch extends AsyncTask<String,BookItem,Void> { public ListView list; public AmazonItemA
public class AsyncBookSearch extends AsyncTask<String,BookItem,Void> {
public ListView list;
public AmazonItemAdapter<BookItem> adapter;
public AsyncBookSearch(ListView l,AmazonItemAdapter<BookItem> ad) {
list = l;
adapter = ad;
}
@Override
protected Void doInBackground(String... keywords) {
// TODO Auto-generated method stub
new BookSearch(keywords[0],list,adapter).parse();
return null;
}
}
目前我不能用Java编写这样的代码。我必须在几乎所有涉及的类中引入不必要的耦合,这只会使事情变得更加复杂,因为现在不仅每个实例需要担心它自己的状态,而且还需要担心与它的任务完全无关的对象中的状态。类是Java中的第一类对象(类中的)。您可以将它们分配给变量、传递、从函数返回等等。我想您是想问一些其他问题,但我不确定那个问题可能是什么。也许是关于泛型类型的擦除和具体化?对此的答案可能很有趣 一个你一直在写的粗俗的例子可能会有所帮助 同样,考虑“X有原因”和“X有好用”之类的问题的区别。 编辑:(回答评论:“我还没有看到一个类被传递的例子”(顺便说一句:我仍然认为这是一个关于擦除和物化的问题,但这个具体的评论没有解决它)。我很惊讶你没有。用Java传递类是很常见的。很少有来自真正流行的API的例子会不假思索地出现在我脑海中:
- Hibernate/JPA实体管理器根据映射对象的类及其主键查找映射对象;例如:
Invoice i=entityManager.find(Invoice.class,12l)
- GWT使用一个特殊的工厂来注入只存在于生成的javascript(或以其他方式参数化)中的类;该方法采用类的实例来创建;例如:
Resource res1=GWT.create(MyResources.class);
- Spring的ApplicationContext根据传递给getBean方法的类为您提供bean;因此您可以这样做:
DataSource default=ApplicationContext.getBean(DataSource.class);
- 类实例用于C#使用反射(Java不能,因为它在运行时会擦除泛型类型)的罕见情况;这种模式有时被称为“类标记”
回答另一个问题:在运行时创建和修改类是常用的,但主要由Java基础设施使用:应用程序服务器、库。看看JMockit。在方法调用期间,您实际上可以动态修改现有类或替换其方法。我不认为您的问题真正是关于类的定义“第一类”对象。我怀疑这确实与java如何处理泛型有关。 我认为您需要理解类型擦除:在您的示例中,您基本上希望编写如下内容
void foo<T>{
T bar = new T();
}
void foo{
T bar=新的T();
}
但这是不可能的,因为在运行时,没有关于T类实际是什么的信息,因为:
在实例化泛型类型时,
编译器通过
一种称为类型擦除的技术-a
编译器删除所有
与类型参数相关的信息
和类或类中的类型参数
类型擦除支持Java
使用泛型的应用程序
保持与的二进制兼容性
Java库和应用程序
是在泛型之前创建的
类是第一类。它们是类的对象。它们可以分配给变量和字段,作为参数传递,甚至可以动态创建 您面临的问题是泛型类型没有具体化,它们只在编译时可见。此外,由于构造函数不是继承的,除非您确切知道要创建哪个类,否则无法知道是否存在具有所需参数的构造函数。解决此问题的一种方法是传入f工厂班
public class AsyncItemSearch<T extends GenericItemSearch<S>,S extends GenericItem> extends AsyncTask<String,T,Void> {
public ListView list;
public AmazonItemAdapter<S> adapter;
public GenericItemSearchFactory<T> factory;
public AsyncBookSearch(ListView l,AmazonItemAdapter<S> ad, GenericItemSearchFactory<T> factory) {
list = l;
adapter = ad;
this.factory = factory;
}
@Override
protected Void doInBackground(String... keywords) {
this.factory.getInstance(keywords[0],list,adapter).parse();
return null;
}
}
公共类AsyncItemSearch扩展了AsyncTask{
公共列表视图列表;
公共适配器;
公共通用搜索工厂;
公共AsyncBookSearch(ListView l、AmazonimaDapter ad、GenericItemSearchFactory){
列表=l;
适配器=ad;
这个工厂=工厂;
}
@凌驾
受保护的Void doInBackground(字符串…关键字){
this.factory.getInstance(关键字[0],列表,适配器).parse();
返回null;
}
}
< /代码> 我不认为类是第一类对象,相反,我会说<代码>类< /代码>是反射API的一部分,因为你不能像其他更动态的语言那样自由地使用它。也就是说,你不能在没有反射的情况下创建新的实例。
主要原因是java的元模型。您不能覆盖静态方法,并且类中存在的构造函数不一定存在于其子类中。这也是您的代码new t(关键字[0],列表,适配器)
无法工作的原因,子类可能没有这样的构造函数
因此,在java中,类对象没有任何用处,因为您肯定需要反射来检查代码在运行时是否有效
另一个主题是泛型类型参数。您不能执行t.class
,因为
public class AsyncItemSearch<T extends GenericItemSearch<S>,S extends GenericItem> extends AsyncTask<String,T,Void> {
public ListView list;
public AmazonItemAdapter<S> adapter;
public GenericItemSearchFactory<T> factory;
public AsyncBookSearch(ListView l,AmazonItemAdapter<S> ad, GenericItemSearchFactory<T> factory) {
list = l;
adapter = ad;
this.factory = factory;
}
@Override
protected Void doInBackground(String... keywords) {
this.factory.getInstance(keywords[0],list,adapter).parse();
return null;
}
}
public Foo<T extends Bar> {
private Class<T> barClass;
public Foo(Class<T> barClass) {
this.barClass = barClass;
}
public T createSomeBar(String arg) {
try {
// the bar contract says that subclasses must have such a constructor
return barClass.getConstructor(String.class).newInstance(arg);
} catch ... // the contract was violated, do proper handling
}
}
public class AsyncItemSearch<T extends GenericItemSearch<S>,S extends GenericItem> extends AsyncTask<String,T,Void> {
private Constructor<T> searchConstructor;
public ListView list;
public AmazonItemAdapter<S> adapter;
public AsyncBookSearch(Class<T> theClass, ListView l,AmazonItemAdapter<S> ad) {
list = l;
adapter = ad;
searchConstructor = theClass.getConstructor(String.class, ListView.class, AmazonItemAdapter<S>.class);
}
@Override
protected Void doInBackground(String... keywords) {
// TODO Auto-generated method stub
searchConstructor.newInstance(keywords[0],list,adapter).parse();
return null;
}
}
AmazonItemAdapter<Book> amazonAdapter = new AmazonBookAdapter();
AsyncItemSearch<BookSearch,Book> s =
new AsyncItemSearch<BookSearch,Book>(
BookSearch.class, myListView, amazonAdapter
);
s.doInBackground("have", "at", "thee", "!");