Java Language
クラスとオブジェクト
サーチ…
前書き
オブジェクトには状態と振る舞いがあります。例:犬には、色、名前、品種、行動などの状態があり、尾を振ったり、吠えたり、食べたりしています。オブジェクトはクラスのインスタンスです。
クラス - クラスは、その型のオブジェクトがサポートする動作/状態を記述するテンプレート/青写真として定義することができます。
構文
- class Example {} //クラスキーワード、名前、本文
最も簡単なクラス
class TrivialClass {}
クラスは最低でもclass
キーワード、名前、および本文から成り立ちます。空であってもかまいません。
new
演算子でクラスをインスタンス化します。
TrivialClass tc = new TrivialClass();
オブジェクトメンバと静的メンバ
このクラスでは:
class ObjectMemberVsStaticMember {
static int staticCounter = 0;
int memberCounter = 0;
void increment() {
staticCounter ++;
memberCounter++;
}
}
次のコードスニペット:
final ObjectMemberVsStaticMember o1 = new ObjectMemberVsStaticMember();
final ObjectMemberVsStaticMember o2 = new ObjectMemberVsStaticMember();
o1.increment();
o2.increment();
o2.increment();
System.out.println("o1 static counter " + o1.staticCounter);
System.out.println("o1 member counter " + o1.memberCounter);
System.out.println();
System.out.println("o2 static counter " + o2.staticCounter);
System.out.println("o2 member counter " + o2.memberCounter);
System.out.println();
System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.staticCounter);
// the following line does not compile. You need an object
// to access its members
//System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.memberCounter);
この出力を生成する:
o1 static counter 3
o1 member counter 1
o2 static counter 3
o2 member counter 2
ObjectMemberVsStaticMember.staticCounter = 3
注意: static
メンバーはオブジェクト上ではなく、クラス上で呼び出すようにしてください 。それはJVMのための違いはありませんが、人間の読者はそれを感謝します。
static
メンバーはクラスの一部であり、クラスごとに1回のみ存在します。インスタンスには非static
メンバーが存在し、インスタンスごとに独立したコピーがあります。これは、メンバーにアクセスするためにそのクラスのオブジェクトにアクセスする必要があることも意味します。
オーバーロードメソッド
時々、異なる種類の入力に対して同じ機能を記述する必要があります。そのとき、同じメソッド名を異なるパラメータセットで使用することができます。それぞれの異なるパラメータセットはメソッドシグネチャとして知られています。例に見られるように、単一のメソッドは複数の署名を持つことができます。
public class Displayer {
public void displayName(String firstName) {
System.out.println("Name is: " + firstName);
}
public void displayName(String firstName, String lastName) {
System.out.println("Name is: " + firstName + " " + lastName);
}
public static void main(String[] args) {
Displayer displayer = new Displayer();
displayer.displayName("Ram"); //prints "Name is: Ram"
displayer.displayName("Jon", "Skeet"); //prints "Name is: Jon Skeet"
}
}
利点は、2つの異なる入力数で同じ機能が呼び出されることです。渡している入力に従ってこのメソッドを呼び出すと(この場合は1つの文字列値か2つの文字列値)、対応するメソッドが実行されます。
メソッドはオーバーロードすることができます:
渡されたパラメータの数に基づいています 。
例:
method(String s)
およびmethod(String s1, String s2)
。
パラメータの順序に基づいています 。
例:
method(int i, float f)
およびmethod(float f, int i))
。
注意:戻り値の型を変更するだけでメソッドをオーバーロードすることはできません( int method()
はString method()
と同じString method()
なされ、試行されるとRuntimeException
がスローされます)。戻り値の型を変更する場合は、オーバーロードするためにパラメータを変更する必要があります。
基本的なオブジェクトの構築と使用
オブジェクトは自分のクラスに入っているので、簡単な例は車です(詳細な説明は以下を参照してください):
public class Car {
//Variables describing the characteristics of an individual car, varies per object
private int milesPerGallon;
private String name;
private String color;
public int numGallonsInTank;
public Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
//this is where an individual object is created
public Car(int mpg, int, gallonsInTank, String carName, String carColor){
milesPerGallon = mpg;
name = carName;
color = carColor;
numGallonsInTank = gallonsInTank;
}
//methods to make the object more usable
//Cars need to drive
public void drive(int distanceInMiles){
//get miles left in car
int miles = numGallonsInTank * milesPerGallon;
//check that car has enough gas to drive distanceInMiles
if (miles <= distanceInMiles){
numGallonsInTank = numGallonsInTank - (distanceInMiles / milesPerGallon)
System.out.println("Drove " + numGallonsInTank + " miles!");
} else {
System.out.println("Could not drive!");
}
}
public void paintCar(String newColor){
color = newColor;
}
//set new Miles Per Gallon
public void setMPG(int newMPG){
milesPerGallon = newMPG;
}
//set new number of Gallon In Tank
public void setGallonsInTank(int numGallons){
numGallonsInTank = numGallons;
}
public void nameCar(String newName){
name = newName;
}
//Get the Car color
public String getColor(){
return color;
}
//Get the Car name
public String getName(){
return name;
}
//Get the number of Gallons
public String getGallons(){
return numGallonsInTank;
}
}
オブジェクトはそのクラスのインスタンスです 。したがって、 オブジェクトを作成する 方法は、メインクラス(Javaではメインメソッド、AndroidではonCreate) の2つの方法のいずれかで Carクラスを呼び出します。
オプション1
`Car newCar = new Car(30, 10, "Ferrari", "Red");
オプション1は、基本的に、オブジェクトの作成時にCarに関するすべてのことをプログラムに伝えます。車のプロパティを変更するには、 repaintCar
メソッドなどのメソッドの1つを呼び出す必要があります。例:
newCar.repaintCar("Blue");
注意:メソッドに正しいデータ型を渡してください。上記の例では、データ型が正しい限り 、 repaintCar
メソッドに変数を渡すこともできます。
これはオブジェクトのプロパティを変更する例でした。オブジェクトのプロパティを受け取るには、戻り値( void
ではないメソッドを意味しvoid
)を持つCarクラスのメソッドを使用する必要がありvoid
。例:
String myCarName = newCar.getName(); //returns string "Ferrari"
オプション1は、作成時にすべてのオブジェクトのデータがある場合に最適なオプションです。
オプション2
`Car newCar = new Car();
オプション2は同じ効果を得ますが、オブジェクトを正しく作成するにはさらに多くの作業が必要です。私はこのクラスをCarクラスで思い出したいと思います:
public void Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
作成するオブジェクトに実際にパラメータを渡す必要はありません。これは、オブジェクトのすべての側面を持っていないが、持っている部品を使用する必要がある場合に非常に便利です。これは、オブジェクトの各インスタンス変数に汎用データを設定します。存在しないデータを呼び出すと、エラーはスローされません。
注意:初期化していないオブジェクトの部分を後で設定する必要があることを忘れないでください。例えば、
Car myCar = new Car();
String color = Car.getColor(); //returns empty string
これは、すべてのデータで初期化されていないオブジェクトの間でよく見かける間違いです。 スタンドアロンの変数 ( public Car(){}
)で空のCarオブジェクトを作成できるコンストラクタは存在しますが、myCarの一部は実際にはカスタマイズされていないため、エラーは回避されました。 カーオブジェクトの作成の正しい例:
Car myCar = new Car();
myCar.nameCar("Ferrari");
myCar.paintCar("Purple");
myCar.setGallonsInTank(10);
myCar.setMPG(30);
また、メインクラスのメソッドを呼び出してオブジェクトのプロパティを取得することを思い出してください。例:
String myCarName = myCar.getName(); //returns string "Ferrari"
コンストラクタ
コンストラクターは、クラスの後に名前が付けられ、戻り値のない特別なメソッドであり、オブジェクトの構築に使用されます。メソッドのようなコンストラクターは、入力パラメーターを取ることができます。コンストラクタはオブジェクトの初期化に使用されます。抽象クラスはコンストラクタも持つことができます。
public class Hello{
// constructor
public Hello(String wordToPrint){
printHello(wordToPrint);
}
public void printHello(String word){
System.out.println(word);
}
}
// instantiates the object during creating and prints out the content
// of wordToPrint
コンストラクタはいくつかの点でメソッドとは異なることを理解することが重要です。
コンストラクターは、修飾子
public
、private
、およびprotected
のみを取ることができ、abstract
、final
、static
、またはsynchronized
宣言することはできません。コンストラクターには戻り値の型はありません。
コンストラクターはクラス名と同じ名前を付けなければなりません(MUST)。
Hello
例では、Hello
オブジェクトのコンストラクタ名はクラス名と同じです。this
キーワードはコンストラクタ内で追加の使い方があります。this.method(...)
は現在のインスタンスのメソッドを呼び出しますが、this(...)
は現在のクラスの別のコンストラクタを参照しています。
コンストラクターは、 super
というキーワードを使用して継承を介して呼び出すこともできます。
public class SuperManClass{
public SuperManClass(){
// some implementation
}
// ... methods
}
public class BatmanClass extends SupermanClass{
public BatmanClass(){
super();
}
//... methods...
}
Java言語仕様#8.8および#15.9を参照してください。
static初期化子を使用してstatic finalフィールドを初期化する
1つ以上の式を使用する必要があるstatic final
フィールドを初期化するには、 static
初期化子を使用して値を割り当てます。次の例では、変更不可能な一連のString
初期化します。
public class MyClass {
public static final Set<String> WORDS;
static {
Set<String> set = new HashSet<>();
set.add("Hello");
set.add("World");
set.add("foo");
set.add("bar");
set.add("42");
WORDS = Collections.unmodifiableSet(set);
}
}
メソッドのオーバーロードとオーバーライドの説明
メソッドのオーバーライドとオーバーロードは、Javaでサポートされている2種類の多態性です。
メソッドのオーバーロード
メソッドのオーバーロード(静的多態性とも呼ばれます)は、1つのクラスに同じ名前の2つ(またはそれ以上)のメソッド(関数)を持つことができる方法です。はい、そのように簡単です。
public class Shape{
//It could be a circle or rectangle or square
private String type;
//To calculate area of rectangle
public Double area(Long length, Long breadth){
return (Double) length * breadth;
}
//To calculate area of a circle
public Double area(Long radius){
return (Double) 3.14 * r * r;
}
}
このようにして、ユーザーは、それが持つ形状のタイプに応じて、同じ方法をエリアに対して呼び出すことができます。
しかし実際の質問は、Javaコンパイラがどのメソッド本体を実行するのかを区別する方法です。
Javaでは、 メソッド名 ( area()
は同じでも引数のメソッドが異なる場合でもメソッド名は 同じであることがわかりました。
オーバーロードされたメソッドは、異なる引数リスト(量と型)を持たなければなりません。
それは、我々はこのような正方形の面積を計算する別のメソッドを追加することはできないと言われています: public Double area(Long side)
この場合、円の領域メソッドと衝突し、Javaコンパイラのあいまいさを引き起こすからです。
神様、ありがとうございました。
戻り値の型が異なる可能性があります。
アクセス修飾子が異なる可能性があります。
異なる例外をスローすることがあります。
なぜこれは静的多型と呼ばれていますか?
実際には引数の実際の数と引数のコンパイル時の型に基づいて、オーバーロードされるメソッドが呼び出されるのはコンパイル時に決定されるからです。
メソッドのオーバーロードを使用する一般的な理由の1つは、コードが提供するシンプルさです。たとえば、ほとんどすべての型の引数を取る
String.valueOf()
を覚えていますか?シーンの後ろに書かれているものはおそらくこのようなものです:
static String valueOf(boolean b)
static String valueOf(char c)
static String valueOf(char[] data)
static String valueOf(char[] data, int offset, int count)
static String valueOf(double d)
static String valueOf(float f)
static String valueOf(int i)
static String valueOf(long l)
static String valueOf(Object obj)
メソッドオーバーライド
さて、メソッドのオーバーライド(はい、それを正しく推測する、それは動的な多態性とも呼ばれます)は、やや面白い複雑なトピックです。
メソッドオーバーライドでは、親クラスによって提供されたメソッド本体を上書きします。とった?いいえ?例を見てみましょう。
public abstract class Shape{
public abstract Double area(){
return 0.0;
}
}
そこでShapeというクラスがあり、それはおそらく形状の領域を返すareaというメソッドを持っています。
CircleとRectangleという2つのクラスがあるとしましょう。
public class Circle extends Shape {
private Double radius = 5.0;
// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return 3.14 * radius * radius;
}
}
同様に矩形クラス:
public class Rectangle extends Shape {
private Double length = 5.0;
private Double breadth= 10.0;
// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return length * breadth;
}
}
したがって、両方の子クラスで親( Shape
)クラスによって提供されるメソッド本体が更新されました。今質問はどのように結果を見ることですか?さて、それは古いpsvm
方法を行うことができます。
public class AreaFinder{
public static void main(String[] args){
//This will create an object of circle class
Shape circle = new Circle();
//This will create an object of Rectangle class
Shape rectangle = new Rectangle();
// Drumbeats ......
//This should print 78.5
System.out.println("Shape of circle : "+circle.area());
//This should print 50.0
System.out.println("Shape of rectangle: "+rectangle.area());
}
}
うわー!それは素晴らしいことではありませんか?同じ型の2つのオブジェクトが同じメソッドを呼び出し、異なる値を返す私の友人、それは動的多型の力です。
これら2つの違いをよりよく比較するためのチャートは次のとおりです。
メソッドのオーバーロード | メソッドオーバーライド |
---|---|
メソッドのオーバーロードは、プログラムの可読性を高めるために使用されます。 | メソッドオーバーライドは、そのスーパークラスによって既に提供されているメソッドの特定の実装を提供するために使用されます。 |
メソッドのオーバーロードはクラス内で実行されます。 | メソッドのオーバーライドは、IS-A(継承)関係を持つ2つのクラスで行われます。 |
メソッドのオーバーロードの場合、パラメータは異なる必要があります。 | メソッドオーバーライドの場合、パラメータは同じでなければなりません。 |
メソッドのオーバーロードは、コンパイル時の多態性の例です。 | メソッドのオーバーライドは実行時の多態性の例です。 |
Javaでは、メソッドの戻り値の型を変更するだけでは、メソッドのオーバーロードを実行できません。戻り値の型は、メソッドのオーバーロードで同じか異なることができます。しかし、パラメータを変更する必要があります。 | 戻り値の型は、メソッドのオーバーライドでは同じか共変でなければなりません。 |