回顾Java的基础
序言
我在复习Java时,注意到了一些基础部分有些微妙的地方。
我想记录下自己的理解。
只需要一个选项,用中文将以下内容进行释义:
参照传递与值传递
参照传递 -> 在内存中传递位置
值传递 -> 直接传递值
用Java行不行呢?
在Java中,只有传值的方式。原始类型直接传递其值,而对象类型则是传递引用值。
参照值传递是指…
将指针传递给方法(指向数据在内存中的位置的信息),因此当将引用值传递给方法时,可以操作原始值。
public void sampleMethod(Object o){
o = 1;
}
然而,如果执行了new操作,会导致引用值的改变,因此即使在之后进行修改也不会对原始值产生影响,必须返回才能使用新产生的引用值。
public void sampleMethod(Object o){
o = new Object();
o = 1;
}
关于String
String是一个对象类型,因此是通过引用传递的。
但是即使替换了值,原始值也不会改变。
→ 这是因为String是一个不可变类。
每次对String进行更改时,实际上会创建一个新的对象(指针指向新的对象)。
因此无法修改原始对象。
因此,尽管结果相同,但它与传值不同。
作文
将一个班级纳入另一个班级中
为什么你在这里?
由于要使用其他类,所以存在继承,但是使用继承可能会导致意外的行为。
public class InstrumentedHashSet<E> extends HashSet<E> {
private int addCount = 0;
public InstrumentedHashSet(){
}
@Override
public boolean add(E e){
addCount++;
return super.add(e);
}
@Override
// addAllは内部的に引数をループしてaddしている
// そのためこのクラスではオーバーライドされたaddが使われカウントがaddの分とaddAllの分重なって進んでしまう。
// つまり継承してメソッドをオーバーライドする場合、対象メソッドが別のオーバーライドしたメソッドを利用しているとその影響を受けてしまう。
public boolean addAll(Collection<? extends E> c){
addCount += c.size();
return super.addAll(c);
}
public int getAddCount(){
return addCount;
}
}
<作文> (Zuò
// 転送クラス
// 別にこれを作らなくてもコンポジション自体はできる。
public class ForwardingSet<E> implements Set<E>{
// コンポジション
private final Set<E> s;
// ここで使われるSetはあくまで引数で渡されたもの
public ForwardingSet(Set<E> s){
this.s = s;
}
public void clear(){
s.clear();
}
public boolean add(E e){
return s.add(e);
}
public boolean addAll(Collection<? extends E> c){
return s.addAll(c);
}
// Setの抽象メソッドをOverrideする(省略)
}
// ラッパークラス
public class RapperSet<E> extends ForwardingSet<E>{
private int addCount = 0;
// スーパークラスのベースにしたいSetを渡す
public RapperSet(Set<E> e){
super(e);
}
@Override
public boolean add(E e){
addCount++;
return super.add(e);
}
@Override
public boolean addAll(Collection<? extends E> c){
addCount += c.size();
// ここで使われているaddAll()はスーパークラスで使われているaddAll()
// つまり引数として渡されたクラスのaddAll()。rapperSetのadd()は関係ない
return super.addAll(c);
}
public int getAddCount(){
return addCount;
}
}