βμ κ·Ό κΆνμ κ°λ₯ν ν μ’νμβ
μ κ·Ό μ νμ | μ€λͺ |
---|---|
private | λ©€λ²λ₯Ό μ μΈν ν±λ 벨 ν΄λμ€μμλ§ μ κ·Όν μ μλ€. |
package-private | λ©€λ²κ° μμλ ν¨ν€μ§ μμ λͺ¨λ ν΄λμ€μμ μ κ·Όν μ μλ€. μ κ·Ό μ νμλ₯Ό λͺ μνμ§ μμμ λ μ μ©λλ ν¨ν€μ§ μ κ·Όμμ€μ΄λ€(λ¨, μΈν°νμ΄μ€μ λ©€λ²λ κΈ°λ³Έμ μΌλ‘ publicμ΄ μ μ©λλ€). |
protected | package-privateμ μ κ·Ό λ²μλ₯Ό ν¬ν¨νλ©°, μ΄ λ©€λ²λ₯Ό μ μΈν ν΄λμ€μ νμ ν΄λμ€μμλ μ κ·Όν μ μλ€. |
public | λͺ¨λ κ³³μμ μ κ·Όν μ μλ€. |
protected
μ public
μ κ³΅κ° APIμpublic static final
λ‘ κ³΅κ°ν΄λ μ’μTEST_VALUE
public
ν΄λμ€λ μ΄λ ν public
νλλ κ°μ§λ©΄ μ λ¨.βνλλ€μ λͺ¨λ
private
μΌλ‘ λ°κΎΈκ³ , μ κ·Όμ(getter)λ₯Ό μ 곡νμβ
class Point {
public double x;
public double y;
}
// μ κ·Όμμ λ³κ²½μ(mutator) λ©μλλ₯Ό νμ©ν΄ λ°μ΄ν°λ₯Ό μΊ‘μννλ€.
class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() { return x; }
public double getY() { return y; }
public void setX(double x) { this.x = x; }
public void setY(double y) { this.y = y; }
}
βν΄λμ€λ κΌ νμν κ²½μ°κ° μλλΌλ©΄ λΆλ³μ΄μ΄μΌ ν¨β
String
, BigInteger
, BigDecimal
λ±1) κ°μ²΄μ μνλ₯Ό λ³κ²½νλ λ©μλ(λ³κ²½μ)λ₯Ό μ 곡νμ§ μλλ€.
2) ν΄λμ€λ₯Ό νμ₯ν μ μλλ‘ νλ€.
3) λͺ¨λ νλλ₯Ό final
λ‘ μ μΈνλ€.
4) λͺ¨λ νλλ₯Ό private
μΌλ‘ μ μΈνλ€.
5) μμ μΈμλ λ΄λΆμ κ°λ³ μ»΄ν¬λνΈμ μ κ·Όν μ μλλ‘ νλ€.
readObject
λ©μλ λͺ¨λμμ λ°©μ΄μ 볡μ¬λ₯Ό μννμ.private final
μ΄μ΄μΌ ν¨βμ»΄ν¬μ§μ κ³Ό μ λ¬μ μ νμ©νμβ
// μλͺ»λ μ - μμμ μλͺ» μ¬μ©νλ€!
public class InstrumentedHashSet<E> extends HashSet<E> {
// μΆκ°λ μμμ μ
private int addCount = 0;
public InstrumentedHashSet() {
}
public InstrumentedHashSet(int initCap, float loadFactor) {
super(initCap, loadFactor);
}
@Override public boolean add(E e) {
addCount++;
return super.add(e);
}
@Override public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
public static void main(String[] args) {
InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
s.addAll(List.of("ν±", "νν", "ν"));
System.out.println(s.getAddCount());
}
}-
β main
λ©μλκ° μ€νλλ©΄ μ«μ λͺμ΄ μΆλ ₯ λ κΉ?
HashSet
μ addAll
λ©μλκ° λ΄λΆμμ add
λ©μλλ₯Ό νΈμΆνκΈ° λλ¬Έ(self-use; μκΈ°μ¬μ©).super.addAll
λ©μλκ° νΈμΆλμμ λ, InstrumentedHashSet
μ add λ©μλκ° 3λ² νΈμΆλκΈ° λλ¬Έμ 6μ΄ μΆλ ₯ λ¨.β μ»΄ν¬μ§μ μ μ¬μ©ν΄ μμμ λ¬Έμ λ₯Ό νΌνμ
private
νλλ‘ κΈ°μ‘΄ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μ°Έμ‘°νκ² νλ λ°©μ.// μ¬μ¬μ©ν μ μλ μ λ¬ ν΄λμ€
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) { this.s = s; }
public void clear() { s.clear(); }
public boolean contains(Object o) { return s.contains(o); }
public boolean isEmpty() { return s.isEmpty(); }
public int size() { return s.size(); }
public Iterator<E> iterator() { return s.iterator(); }
public boolean add(E e) { return s.add(e); }
public boolean remove(Object o) { return s.remove(o); }
public boolean containsAll(Collection<?> c)
{ return s.containsAll(c); }
public boolean addAll(Collection<? extends E> c)
{ return s.addAll(c); }
public boolean removeAll(Collection<?> c)
{ return s.removeAll(c); }
public boolean retainAll(Collection<?> c)
{ return s.retainAll(c); }
public Object[] toArray() { return s.toArray(); }
public <T> T[] toArray(T[] a) { return s.toArray(a); }
@Override public boolean equals(Object o)
{ return s.equals(o); }
@Override public int hashCode() { return s.hashCode(); }
@Override public String toString() { return s.toString(); }
}
// λνΌ ν΄λμ€ - μμ λμ μ»΄ν¬μ§μ
μ μ¬μ©
public class InstrumentedSet<E> extends ForwardingSet<E> {
private int addCount = 0;
public InstrumentedSet(Set<E> s) {
super(s);
}
@Override public boolean add(E e) {
addCount++;
return super.add(e);
}
@Override public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
public static void main(String[] args) {
InstrumentedSet<String> s = new InstrumentedSet<>(new HashSet<>());
s.addAll(List.of("ν±", "νν", "ν"));
System.out.println(s.getAddCount());
}
}
β main
λ©μλκ° μ€νλλ©΄ μ«μ λͺμ΄ μΆλ ₯ λ κΉ?
super.addAll
λ©μλκ° νΈμΆλμμ λ, InstrumentedSet
μ add
λ©μλκ° μλ μ λ¬ν΄λμ€μ μ‘΄μ¬νλ s
μΈμ€ν΄μ€μ add
λ©μλκ° νΈμΆλκΈ° λλ¬Έμ μ μμ μΌλ‘ λμν¨.βκΌ νμν κ²½μ°μλ§ μμκ°λ₯νλλ‘ μ€κ³, λλ¨Έμ§ κ²½μ°μ μμκΈμ§β
protected
λ©μλ ννλ‘ κ³΅κ°ν΄μΌ ν μλ μμ. ex) java.util.AbstractList
μ removeRange
λ©μλclone
κ³Ό readObject
λͺ¨λ μ§μ μ μΌλ‘λ κ°μ μ μΌλ‘λ μ¬μ μ κ°λ₯ λ©μλλ₯Ό νΈμΆν΄μλ μ λ¨β ν΄λμ€λ₯Ό μμμ©μΌλ‘ μ€κ³νλ €λ©΄ μμ²λ λ Έλ ₯μ΄ λ€κ³ κ·Έ ν΄λμ€μ μκΈ°λ μ μ½λ μλΉν¨..
β ν΄λμ€λ₯Ό νμ₯ν΄μΌ ν λͺ νν μ΄μ κ° μλ€λ©΄ μμμ κΈμ§νμ
final
λ‘ μ μΈprivate
μ΄λ package-private
μΌλ‘ μ μΈ ν public
μ μ ν©ν°λ¦¬ μ 곡βμΌλ°μ μΌλ‘ λ€μ€ ꡬνμ© νμ μΌλ‘ μΈν°νμ΄μ€κ° κ°μ₯ μ ν©β
λ€μ€μμ κ°λ₯ μ¬λΆ | κ³μΈ΅ ꡬ쑰 | |
---|---|---|
μΆμ ν΄λμ€ | λΆκ° | μν κ΄κ³ |
μΈν°νμ΄μ€ | κ°λ₯ | x |
public interface Singer {
AudioClip sing(Song s);
}
public interface Songwriter {
Song compose(int chartPosition);
}
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
@implSpec
μλ°λ
νκ·Έλ₯Ό λΆμ¬ λ¬Έμνν΄μΌ ν¨.AbstractSet
, AbstractList
λ±// 골격 ꡬν ν΄λμ€
public abstract class AbstractMapEntry<K,V> implements Map.Entry<K,V> {
// λ³κ²½ κ°λ₯ν μνΈλ¦¬λ μ΄ λ©μλλ₯Ό λ°λμ μ¬μ μν΄μΌ νλ€.
@Override public V setValue(V value) {
throw new UnsupportedOperationException();
}
// Map.Entry.equalsμ μΌλ° κ·μ½μ ꡬννλ€.
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry) o;
return Objects.equals(e.getKey(), getKey())
&& Objects.equals(e.getValue(), getValue());
}
// Map.Entry.hashCodeμ μΌλ° κ·μ½μ ꡬννλ€.
@Override public int hashCode() {
return Objects.hashCode(getKey())
^ Objects.hashCode(getValue());
}
@Override public String toString() {
return getKey() + "=" + getValue();
}
}
βμ¬κ°νκ² μλͺ»λ μΈν°νμ΄μ€λ μ΄λ₯Ό ν¬ν¨ν APIμ μ΄λ€ μ¬μμ λͺ°κ³ μ¬μ§ μ μ μλ€.β
β κΈ°μ‘΄ μΈν°νμ΄μ€μ λν΄νΈ λ©μλλ‘ μ λ©μλλ₯Ό μΆκ°νλ μΌμ κΌ νμν κ²½μ°κ° μλλΌλ©΄ νΌνμ
βμΈν°νμ΄μ€λ νμ μ μ μ©λ, μμ μΈν°νμ΄μ€ μν° ν¨ν΄ μ§μβ
// μμ μΈν°νμ΄μ€ μν°ν¨ν΄ - μ¬μ©κΈμ§!
public interface PhysicalConstants {
// μ보κ°λλ‘ μ (1/λͺ°)
static final double AVOGADROS_NUMBER = 6.022_140_857e23;
// λ³ΌμΈ λ§ μμ (J/K)
static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23;
// μ μ μ§λ (kg)
static final double ELECTRON_MASS = 9.109_383_56e-31;
}
final
μ΄ μλ ν΄λμ€κ° μμ μΈν°νμ΄μ€λ₯Ό ꡬννλ€λ©΄ λͺ¨λ νμ ν΄λμ€μ μ΄λ¦κ³΅κ°μ΄ κ·Έ μΈν°νμ΄μ€κ° μ μν μμλ€λ‘ μ€μΌλμ΄ λ²λ¦ΌInteger
μ MIN_VALUE
μμ// μμ μ νΈλ¦¬ν° ν΄λμ€
public class PhysicalConstants {
private PhysicalConstants() { } // μΈμ€ν΄μ€ν λ°©μ§
// μ보κ°λλ‘ μ (1/λͺ°)
public static final double AVOGADROS_NUMBER = 6.022_140_857e23;
// λ³ΌμΈ λ§ μμ (J/K)
public static final double BOLTZMANN_CONST = 1.380_648_52e-23;
// μ μ μ§λ (kg)
public static final double ELECTRON_MASS = 9.109_383_56e-31;
}
// μμ μ¬μ©μ
PhysicalConstants.AVOGADROS_NUMBER;
βνκ·Έ λ¬λ¦° ν΄λμ€λ ν΄λμ€ κ³μΈ΅κ΅¬μ‘°λ₯Ό μ΄μ€νκ² νλ΄λΈ μλ₯β
// νκ·Έ λ¬λ¦° ν΄λμ€ - ν΄λμ€ κ³μΈ΅κ΅¬μ‘°λ³΄λ€ ν¨μ¬ λμλ€!
class Figure {
enum Shape { RECTANGLE, CIRCLE };
// νκ·Έ νλ - νμ¬ λͺ¨μμ λνλΈλ€.
final Shape shape;
// λ€μ νλλ€μ λͺ¨μμ΄ μ¬κ°ν(RECTANGLE)μΌ λλ§ μ°μΈλ€.
double length;
double width;
// λ€μ νλλ λͺ¨μμ΄ μ(CIRCLE)μΌ λλ§ μ°μΈλ€.
double radius;
// μμ© μμ±μ
Figure(double radius) {
shape = Shape.CIRCLE;
this.radius = radius;
}
// μ¬κ°νμ© μμ±μ
Figure(double length, double width) {
shape = Shape.RECTANGLE;
this.length = length;
this.width = width;
}
double area() {
switch(shape) {
case RECTANGLE:
return length * width;
case CIRCLE:
return Math.PI * (radius * radius);
default:
throw new AssertionError(shape);
}
}
}
switch
λ¬Έ λ± μΈλ° μλ μ½λκ° λ§μβ νκ·Έ λ¬λ¦° ν΄λμ€λ κ³μΈ΅κ΅¬μ‘°λ‘ λ°κΏμ μ¬μ©νμ
// νκ·Έ λ¬λ¦° ν΄λμ€λ₯Ό ν΄λμ€ κ³μΈ΅κ΅¬μ‘°λ‘ λ³ν
abstract class Figure {
abstract double area();
}
class Rectangle extends Figure {
final double length;
final double width;
Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override double area() { return length * width; }
}
class Circle extends Figure {
final double radius;
Circle(double radius) { this.radius = radius; }
@Override double area() { return Math.PI * (radius * radius); }
}
βλ€ κ°μ§ μ€μ²© ν΄λμ€μ μ°μ μ€λͺ β
public
λμ°λ―Έ ν΄λμ€ μ©λλ‘ μ¬μ©Calculator.Operation
μ΄κ±° νμ
iterator
)public class MySet<E> extends AbstractSet<E> {
... // μλ΅
@Override public Iterator<E> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<E> {
...
}
}
this
λ₯Ό μ¬μ©ν΄ λ°κΉ₯ μΈμ€ν΄μ€ μ°Έμ‘° κ°λ₯.instanceof
κ²μ¬λ ν΄λμ€μ μ΄λ¦μ΄ νμν μμ
μν λΆκ°βμμ€ νμΌ νλμλ λ°λμ ν±λ 벨 ν΄λμ€(νΉμ ν±λ 벨 μΈν°νμ΄μ€)λ₯Ό νλλ§ λ΄μβ
Utensil.java
// λ ν΄λμ€κ° ν νμΌ(Utensil.java)μ μ μλμλ€. - λ°λΌ νμ§ λ§ κ²!
class Utensil {
static final String NAME = "pan";
}
class Dessert {
static final String NAME = "cake";
}
Dessert.java
// λ ν΄λμ€κ° ν νμΌ(Dessert.java)μ μ μλμλ€. - λ°λΌ νμ§ λ§ κ²!
class Utensil {
static final String NAME = "pot";
}
class Dessert {
static final String NAME = "pie";
}
Main.java
public class Main {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
}
}
javac Main.java Dessert.java
λ‘ μ»΄νμΌ ν κ²½μ°Main.java
λ₯Ό μ»΄νμΌmain
λ©μλ μμμ Utensil
μ°Έμ‘°λ₯Ό λ§λλ©΄ Utensil.java
νμΌμ μ΄ν΄ Utensil
κ³Ό Dessert
λ₯Ό λͺ¨λ μ μDessert.java
λ₯Ό μ²λ¦¬νλ € ν λ, κ°μ ν΄λμ€μ μ μκ° μμμ μκ² λκ³ μ»΄νμΌ μ€λ₯λ₯Ό λ±μ(ν΄λμ€ μ€λ³΅ μ μ)javac Main.java
λλ javac Main.Utensil.java
λ‘ μ»΄νμΌ ν κ²½μ°Main.java
λ₯Ό μ»΄νμΌmain
λ©μλ μμμ Utensil
μ°Έμ‘°λ₯Ό λ§λλ©΄ Utensil.java
νμΌμ μ΄ν΄ Utensil
κ³Ό Dessert
λ₯Ό λͺ¨λ μ μjavac Dessert.java Main.java
λ‘ μ»΄νμΌ ν κ²½μ°Dessert.java
μ μ΄ν΄ Utensil
κ³Ό Dessert
λ₯Ό λͺ¨λ μ μMain.java
μ»΄νμΌβ 2, 3μ 보면 μ»΄νμΌ μμμ λ°λΌ μΆλ ₯κ²°κ³Όκ° λ¬λΌμ§μ νμΈν μ μμ.
Utensil
κ³Ό Dessert
)μ μλ‘ λ€λ₯Έ μμ€ νμΌλ‘ λΆλ¦¬νλ©΄ λ¨// ν±λ 벨 ν΄λμ€λ€μ μ μ λ©€λ² ν΄λμ€λ‘ λ°κΏλ³Έ λͺ¨μ΅
public class Test {
public static void main(String[] args) {
System.out.println(Utensil.NAME + Dessert.NAME);
}
private static class Utensil {
static final String NAME = "pan";
}
private static class Dessert {
static final String NAME = "cake";
}
}