回顾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;
}
}
广告
将在 10 秒后关闭
bannerAds