我正在学习java中的泛型并遇到了这个问题。
我有一个Weather界面。 EarthQuake
和VirginiaWeather
是实现Weather
接口的两个类。这两个类都有一个静态方法 - "parseData"
,它解析来自atom feed的数据。 Main类中的getFeeds
方法有一个参数"String type"
,我用它来找出哪个类&#39}。方法我应该打电话。
任何人都可以帮助我理解是否可以使用泛型来使代码更清洁。我可以将类类型作为参数传递给方法,并使用该类类型在相应的类中调用parseData
方法。
我试着这样做
list.add(T.parseData((Element) nl.item(i)));
但得到了:
对于类型T
,方法parseData(Element)未定义
public class Main {
public static void main(String[] args) {
List<EarthQuake> quakes = getFeeds("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.atom", "quakes");
List<VirginiaWeather> weather = getFeeds("http://alerts.weather.gov/cap/va.php?x=0", "weather");
//Get Earthquake data
System.out.println("Earthquake data");
for (EarthQuake e: quakes)
System.out.printf("%s\t%s\t%f\t%s\n",(e.getDate()),e.getLocation(),e.getMagnitude(),e.getDetails());
//Get Virginia weather data
System.out.println("Virginia Weather");
for (VirginiaWeather vw: weather)
System.out.printf("%s\t%s\t%s\t%s\t%s\n",vw.getUpdated(),vw.getTitle(),vw.getEvent(),vw.getEffective(),vw.getExpires());
}
private static <T> List<T> getFeeds(String url, String type) {
List<T> list = new ArrayList<>();
try {
URL usgsUrl = new URL(url);
URLConnection urlConnection = usgsUrl.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
int response = httpConnection.getResponseCode();
if(response == HttpURLConnection.HTTP_OK)
{
InputStream in = httpConnection.getInputStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(in);
Element element = document.getDocumentElement();
NodeList nl = element.getElementsByTagName("entry");
if(nl != null && nl.getLength() > 0)
for(int i =0 ; i<nl.getLength() ; i++)
{
if(type.equals("quakes"))
{
list.add((T) EarthQuake.parseData((Element) nl.item(i)));
}
if(type.equals("weather"))
{
list.add((T) VirginiaWeather.parseData((Element) nl.item(i)));
}
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
finally{
}
return list;
}
}
答案 0 :(得分:2)
我会使用打字的工厂。首先创建一个界面:
interface WeatherDataFactory<T> {
T parse(Element element);
}
然后编写具体的气象数据工厂:
class VirginiaWeatherDataFactory implements WeatherDataFactory<VirginiaWeather> {
@Override
public VirginiaWeather parse(final Element element) { ... }
}
然后您的getFeeds
方法将如下所示:
private static <T> List<T> getFeeds(String url, WeatherDataFactory<T> factory) {
...
if(nl != null && nl.getLength() > 0) {
for(int i =0 ; i<nl.getLength() ; i++) {
list.add(factory.parse(nl));
}
}
}
顺便说一下,NodeList#item(int)
的大多数实现都像链表那样执行,因为必须遍历整个列表以获取元素 n 。如果列表很大,你的程序将会非常慢。
答案 1 :(得分:1)
为什么不使用Java 8的设施?
private static <T> List<T> getFeeds(String url, Function<Element, T> parser) {
// [..snip..]
for(int i =0 ; i<nl.getLength() ; i++) {
list.add(parser.call((Element) nl.item(i)));
}
// [..snip..]
}
你这样使用它:
List<EarthQuakes> eq = getFeeds("http://....", EarthQuake::parseData);
List<VirginiaWeather> eq = getFeeds("http://....", VirginiaWeather::parseData);
从长远来看,拥有一个管理解析的工厂类可能更有用,而不是在同一个类中合并数据表示和解析。
答案 2 :(得分:0)
您可以使用键入的类。
public interface Weather<T>(){
private static <T> List<T> getFeeds(String url, String type);
}
另一个班级
public class EarthQuake implements Weather<EarthQuake> {
}