我有一个疑问,在Java中的此语句中
class Country {
public Country(String countryName) {
this.countryName = countryName;
this.states = new ArrayList<>();
}
String countryName;
List<State> states;
}
class State {
public State(String stateName) {
this.stateName = stateName;
this.cities = new ArrayList<>();
}
String stateName;
List<City> cities;
}
class City {
public City(String cityName) {
this.cityName = cityName;
}
String cityName;
}
class Geography {
String countryName;
String stateName;
String cityName;
}
List<Country> buildFromGeographies(List<Geography> geos) {
List<Country> result = new ArrayList<>();
for (Geography geo : geos) {
Optional<Country> country1 = result.stream().filter(country -> country.countryName.equals(geo.countryName)).findFirst();
Country country = country1.orElseGet(() -> {
Country newOne = new Country(geo.countryName);
result.add(newOne);
return newOne;
});
Optional<State> state1 = country.states.stream().filter(state -> state.stateName.equals(geo.stateName)).findFirst();
State state = state1.orElseGet(() -> {
State newOne = new State(geo.stateName);
country.states.add(newOne);
return newOne;
});
// taking for granted there is no duplicates in your data set
state.cities.add(new City(geo.cityName));
}
return result;
}
此语句将在内存中存储多少引用,并且A z[]=new A[5];
引用指向z
?
答案 0 :(得分:2)
给出:A[] x = new A[5];
(不要写A x[]
;它是合法的Java,但完全不是惯用语言。请把它看作是假冒的风格。就像误输入代码一样)。假设它在方法内部(因此,它是一个局部变量声明,而不是字段声明)。
这将创建一个名为“ x”的新局部变量,该局部变量仅限于指向对象,并且只能指向A[]
或null
的实例,并且没有其他内容,并且均由编译器进行了验证和运行时。它还会在堆上实例化一个新的数组对象,并将x
变量设置为指向此新创建的对象。
此指针变量本身需要占用一些空间(4或8个字节,具体取决于VM),但是它将像C中一样位于堆栈中。
那么,new A[5]
在内存方面有何作用?
它将创建一个新对象来表示数组本身。该对象包含以下信息:我有多少个元素,我的组件类型是什么。再次与C不同,C仅具有指向数组数据结构的指针,因此您不知道其中可能有什么数据,也不知道其中有多少数据。在Java中,情况并非如此,但是信息(长度和类型)意味着您需要将其显式存储在内存中。您可以观察到:x.length
将返回5,而x.getClass().getComponentType
将返回A.class。在64位VM上,此对象总共约占24个字节(大小为4个字节,组件类型的指针为8个字节,并抛出了一些额外的字节,因为该事物需要标识它代表的是数组)。 / p>
在这24个字节之后,有5个“插槽”,每个插槽占用的字节数与组件类型所需的字节数相同。那个多少钱?取决于A
是什么。
如果A
为:byte
,short
,int
,long
,float
,double
,{{1 }},char
或其他任何内容。
然后,组件大小(以字节为单位)分别为:1、2、4、8、8、4、8、2、1和X,其中X为4或8,具体取决于VM。如今,几乎总是有8个(64位VM)。
在执行期间,VM可能会在内存表中注入一些空白,因为现代的CPU确实非常不喜欢处理64位边界上的东西。 C编译器做同样的事情。