수색…


소개

객체에는 상태와 비헤이비어가 있습니다. 예 : 개에는 상태, 색상, 이름, 품종, 행동 등이 있습니다. 꼬리를 흔들거나, 짖거나, 먹습니다. 객체는 클래스의 인스턴스입니다.

클래스 - 클래스는 해당 유형의 객체가 지원하는 동작 / 상태를 설명하는 템플릿 / 청사진으로 정의 할 수 있습니다.

통사론

  • class Example {} // 클래스 키워드, 이름, 본문

가장 간단한 수업

class TrivialClass {}

클래스는 최소한 class 키워드, 이름 및 본문으로 구성되며 비어있을 수 있습니다.

new 연산자로 클래스를 인스턴스화합니다.

TrivialClass tc = new TrivialClass();

개체 멤버 vs 정적 멤버

이 수업에서 :

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 멤버는 클래스의 일부이며 클래스 당 한 번만 존재합니다. 비 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"
    }
}

장점은 두 개의 서로 다른 입력 수를 사용하여 동일한 기능이 호출된다는 것입니다. 전달중인 입력에 따라 메소드를 호출하는 동안 (이 경우 하나의 문자열 값 또는 두 개의 문자열 값) 해당 메소드가 실행됩니다.

메소드가 오버로드 될 수 있습니다.

  1. 전달 된 매개 변수수를 기반으로합니다.

    예 : method(String s)method(String s1, String s2) .

  1. 매개 변수순서를 기반으로합니다.

    예 : method(int i, float f)method(float f, int i)) .

참고 : 방법이 (바로 반환 형식을 변경하여 오버로드 할 수 없습니다 int 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) 중 하나 에서 Car 클래스를 호출하는 것입니다.

옵션 1

`Car newCar = new Car(30, 10, "Ferrari", "Red");

옵션 1은 본질적으로 개체 생성시 Car에 대한 모든 것을 프로그램에 알려주는 곳입니다. 자동차의 속성을 변경하려면 repaintCar 메서드와 같은 메서드 중 하나를 호출해야합니다. 예:

 newCar.repaintCar("Blue");

주 : 메소드에 올 Y 른 데이터 유형을 전달했는지 확인하십시오. 위 예제 에서 데이터 유형이 올바른 경우 repaintCar 메소드에 변수를 전달할 수도 있습니다.

이것은 객체의 속성을 변경하는 예제였습니다. 객체의 속성을 수신하려면 반환 값 ( void 가 아닌 메서드를 의미 함)을 가진 Car 클래스의 메서드를 사용해야합니다. 예:

String myCarName = newCar.getName();  //returns string "Ferrari"

옵션 1은 생성시 모든 오브젝트의 데이터 를 가지고있을 때 가장 좋은 옵션입니다.

옵션 2

`Car newCar = new Car();

옵션 2는 동일한 효과를 얻지 만 오브젝트를 올바르게 작성하려면 더 많은 작업이 필요합니다. Car 클래스의 Constructor를 상기하고 싶습니다.

public void Car(){
        milesPerGallon = 0;
        name = "";
        color = "";
        numGallonsInTank = 0;
    }

객체를 생성하기 위해 객체에 매개 변수를 실제로 전달할 필요는 없습니다. 이는 오브젝트의 모든면을 가지고 있지 않지만 가지고있는 파트를 사용해야 할 때 매우 유용합니다. 이렇게하면 객체의 각 인스턴스 변수에 일반 데이터가 설정되므로 존재하지 않는 데이터를 호출하면 오류가 발생하지 않습니다.

참고 : 초기화하지 않은 객체의 부분을 나중에 설정해야한다는 것을 잊지 마십시오. 예를 들어,

Car myCar = new Car();
String color = Car.getColor(); //returns empty string

이것은 모든 데이터로 초기화되지 않은 객체들 사이에 공통적 인 실수입니다. 빈 Car 객체를 독립 변수 ( public 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

생성자가 여러 가지 방법으로 메소드와 다르다는 것을 이해하는 것이 중요합니다.

  1. 생성자는 public , privateprotected 라는 수정 자만 사용할 수 있으며 abstract , final , static 또는 synchronized 로 선언 할 수 없습니다.

  2. 생성자에는 반환 유형이 없습니다.

  3. 생성자는 클래스 이름과 동일한 이름을 지정해야합니다 (MUST). Hello 예제에서 Hello 객체의 생성자 이름은 클래스 이름과 동일합니다.

  4. 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 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에서 지원하는 두 가지 형태의 다형성입니다.

메서드 오버로딩

메서드 오버로드 (정적 다형성이라고도 함)는 단일 클래스에서 동일한 이름을 가진 두 개 이상의 메서드 (함수)를 가질 수있는 방법입니다. 네, 그렇게 간단합니다.

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;
    }
}

이렇게하면 사용자는 모양의 유형에 따라 영역에 대해 동일한 메소드를 호출 할 수 있습니다.

하지만 실제 질문은 자바 컴파일러가 어떤 메서드 본문을 실행할지 구분하는 방법입니다.

Well Java는 메서드 이름 (이 경우에는 area() 이 동일 할 수 있지만 인수 메서드가 사용하는 방식이 달라야한다고 분명히했습니다 .

오버로딩 된 메서드는 서로 다른 인수 목록 (수량 및 유형)을 가져야합니다.

그것은 우리가 사각형의 면적을 계산하는 또 다른 방법을 추가 할 수 없다는 것입니다 : public Double area(Long side) 왜냐하면이 경우 원의 면적 방법과 충돌 할 것이고 자바 컴파일러의 모호함 을 야기 할 것이기 때문입니다.

하느님 감사합니다. 오버로드 된 메소드를 작성하는 동안 몇 가지 휴식이 있습니다.

반환 유형이 다를 수 있습니다.

다른 액세스 수정자를 가질 수 있습니다.

다른 예외를 throw 할 수 있습니다.

이것이 정적 다형성이라고 불리는 이유는 무엇입니까?

실제로 오버로드 된 메소드가 호출되기 때문에 실제 인수 수와 인수의 컴파일 타임 유형에 따라 컴파일 타임에 결정됩니다.

메서드 오버로드를 사용하는 일반적인 이유 중 하나는 코드가 제공하는 단순성입니다. 예를 들어 거의 모든 유형의 인수를 취하는 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라는 메소드를 가지고 있습니다.

원과 사각형이라는 두 개의 클래스가 있다고 가정 해 봅시다.

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());            
        
    }
}

와우! 멋지지 않니? 동일한 유형의 두 객체가 동일한 메소드를 호출하고 다른 값을 반환합니다. 내 친구, 그것은 역동적 인 다형성의 힘입니다.

다음 두 차트의 차이점을 더 잘 비교할 수있는 차트가 있습니다.

메서드 오버로딩 메서드 재정의
메서드 오버로드는 프로그램의 가독성을 높이는 데 사용됩니다. 메서드 오버라이드는 이미 수퍼 클래스에서 제공하는 메서드의 특정 구현을 제공하는 데 사용됩니다.
메서드 오버로딩은 클래스 내에서 수행됩니다. 메서드 재정의는 IS-A (상속) 관계가있는 두 클래스에서 발생합니다.
메소드 오버로딩의 경우 매개 변수가 달라야합니다. 메소드 오버라이드의 경우 매개 변수가 동일해야합니다.
메서드 오버로드는 컴파일 시간 다형성의 예입니다. 메서드 오버라이드는 런타임 다형성의 예입니다.
자바에서는 메서드의 반환 형식 만 변경하여 메서드 오버로드를 수행 할 수 없습니다. 반환 형식은 메서드 오버로드에서 같거나 다를 수 있습니다. 그러나 매개 변수를 변경해야합니다. 반환 형식은 메서드 재정의에서 동일하거나 공변이어야합니다.


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow