[java] Java에서 포인터를 어떻게 사용할 수 있습니까?

Java에 포인터가 없다는 것을 알고 있지만 Java 프로그램은 포인터로 만들 수 있으며 Java 전문가 인 소수만 수행 할 수 있다고 들었습니다. 사실인가요?



답변

Java의 모든 객체는 참조이며 포인터처럼 사용할 수 있습니다.

abstract class Animal
{...
}

class Lion extends Animal
{...
}

class Tiger extends Animal
{
public Tiger() {...}
public void growl(){...}
}

Tiger first = null;
Tiger second = new Tiger();
Tiger third;

null 역 참조 :

first.growl();  // ERROR, first is null.    
third.growl(); // ERROR, third has not been initialized.

별칭 문제 :

third = new Tiger();
first = third;

손실 세포 :

second = third; // Possible ERROR. The old value of second is lost.    

먼저 이전 값인 second가 더 이상 필요하지 않음을 먼저 확인하거나 다른 포인터에 second 값을 할당하여이를 안전하게 만들 수 있습니다.

first = second;
second = third; //OK

second에 다른 방식 (NULL, new …)으로 값을 제공하는 것은 잠재적 인 오류와 마찬가지로 그것이 가리키는 객체를 잃을 수 있습니다.

OutOfMemoryErrornew를 호출하고 할당자가 요청 된 셀을 할당 할 수없는 경우 Java 시스템에서 예외 ( )가 발생합니다. 이는 매우 드물며 일반적으로 폭주 재귀로 인해 발생합니다.

언어 관점에서 가비지 수집기에 개체를 버리는 것은 오류가 아닙니다. 프로그래머가 알아야 할 것입니다. 동일한 변수가 다른 시간에 다른 개체를 가리킬 수 있으며 포인터가 참조하지 않으면 이전 값이 회수됩니다. 그러나 프로그램의 논리가 개체에 대한 참조를 하나 이상 유지해야하는 경우 오류가 발생합니다.

초보자는 종종 다음과 같은 오류를 범합니다.

Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed. 

아마 당신이 말하려는 것은 다음과 같습니다.

Tiger tony = null;
tony = third; // OK.

부적절한 주조 :

Lion leo = new Lion();
Tiger tony = (Tiger)leo; // Always illegal and caught by compiler. 

Animal whatever = new Lion(); // Legal.
Tiger tony = (Tiger)whatever; // Illegal, just as in previous example.
Lion leo = (Lion)whatever; // Legal, object whatever really is a Lion.

C의 포인터 :

void main() {
    int*    x;  // Allocate the pointers x and y
    int*    y;  // (but not the pointees)

    x = malloc(sizeof(int));    // Allocate an int pointee,
                                // and set x to point to it

    *x = 42;    // Dereference x to store 42 in its pointee

    *y = 13;    // CRASH -- y does not have a pointee yet

    y = x;      // Pointer assignment sets y to point to x's pointee

    *y = 13;    // Dereference y to store 13 in its (shared) pointee
}

자바의 포인터 :

class IntObj {
    public int value;
}

public class Binky() {
    public static void main(String[] args) {
        IntObj  x;  // Allocate the pointers x and y
        IntObj  y;  // (but not the IntObj pointees)

        x = new IntObj();   // Allocate an IntObj pointee
                            // and set x to point to it

        x.value = 42;   // Dereference x to store 42 in its pointee

        y.value = 13;   // CRASH -- y does not have a pointee yet

        y = x;  // Pointer assignment sets y to point to x's pointee

        y.value = 13;   // Deference y to store 13 in its (shared) pointee
    }
} 

업데이트 : 주석에서 제안했듯이 C에는 포인터 산술이 있다는 점에 유의해야합니다. 그러나 Java에는 없습니다.


답변

Java에는 포인터가 있습니다. Java로 객체를 생성 할 때마다 실제로 객체에 대한 포인터를 생성합니다. 이 포인터는 다른 객체 또는로 설정 될 수 null있으며 원래 객체는 여전히 존재합니다 (가비지 수집 보류).

Java에서 할 수없는 것은 포인터 산술입니다. 특정 메모리 주소를 역 참조하거나 포인터를 증가시킬 수 없습니다.

저수준을 원한다면 Java Native Interface를 사용하는 것이 유일한 방법입니다 . 그런 다음에도 저수준 부분은 C 또는 C ++로 수행해야합니다.


답변

Java에는 포인터 데이터 유형이 없으므로 Java에서 포인터를 사용할 수 없습니다. 소수의 전문가조차도 자바에서 포인터를 사용할 수 없습니다.

마지막 요점 : Java 언어 환경 도 참조하십시오.


답변

Java에는 포인터가 있지만 C ++ 또는 C에서 할 수있는 방식으로 포인터를 조작 할 수 없습니다. 객체를 전달할 때 해당 객체에 대한 포인터를 전달하지만 C ++에서와 같은 의미는 아닙니다. 해당 개체는 역 참조 할 수 없습니다. 네이티브 접근자를 사용하여 값을 설정하면 Java가 포인터를 통해 메모리 위치를 알고 있기 때문에 값이 변경됩니다. 그러나 포인터는 변경할 수 없습니다. 포인터를 새 위치로 설정하려고하면 대신 다른 것과 동일한 이름을 가진 새 로컬 개체가 생성됩니다. 원래 개체는 변경되지 않습니다. 다음은 차이점을 보여주는 간단한 프로그램입니다.

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone {

    public static void main(String[] args) throws java.lang.Exception {
        System.out.println("Expected # = 0 1 2 2 1");
        Cat c = new Cat();
        c.setClaws(0);
        System.out.println("Initial value is " + c.getClaws());
        // prints 0 obviously
        clawsAreOne(c);
        System.out.println("Accessor changes value to " + c.getClaws());
        // prints 1 because the value 'referenced' by the 'pointer' is changed using an accessor.
        makeNewCat(c);
        System.out.println("Final value is " + c.getClaws());
        // prints 1 because the pointer is not changed to 'kitten'; that would be a reference pass.
    }

    public static void clawsAreOne(Cat kitty) {
        kitty.setClaws(1);
    }

    public static void makeNewCat(Cat kitty) {
        Cat kitten = new Cat();
        kitten.setClaws(2);
        kitty = kitten;
        System.out.println("Value in makeNewCat scope of kitten " + kitten.getClaws());
        //Prints 2. the value pointed to by 'kitten' is 2
        System.out.println("Value in makeNewcat scope of kitty " + kitty.getClaws());
        //Prints 2. The local copy is being used within the scope of this method.
    }
}

class Cat {

    private int claws;

    public void setClaws(int i) {
        claws = i;
    }

    public int getClaws() {
        return claws;
    }
}

Ideone.com에서 실행할 수 있습니다.


답변

Java에는 C와 같은 포인터가 없지만 변수에 의해 “참조되는”힙에 새 개체를 만들 수 있습니다. 포인터가 없다는 것은 Java 프로그램이 메모리 위치를 불법적으로 참조하는 것을 막고, 가비지 수집이 Java Virtual Machine에 의해 자동으로 수행되도록하는 것입니다.


답변

Unsafe 클래스를 사용하여 주소와 포인터를 사용할 수 있습니다. 그러나 이름에서 알 수 있듯이 이러한 방법은 안전하지 않으며 일반적으로 나쁜 생각입니다. 잘못된 사용으로 인해 JVM이 무작위로 죽을 수 있습니다 (실제로 C / C ++에서 포인터를 잘못 사용하는 것과 동일한 문제)

포인터에 익숙하고 포인터가 필요하다고 생각할 수 있지만 (다른 방법으로 코딩하는 방법을 모르기 때문에), 그렇지 않다는 것을 알게되고 더 나을 것입니다.


답변

기술적으로 모든 Java 객체는 포인터입니다. 모든 기본 유형은 값입니다. 이러한 포인터를 수동으로 제어 할 수있는 방법은 없습니다. Java는 내부적으로 참조에 의한 전달을 사용합니다.