Java에 포인터가 없다는 것을 알고 있지만 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 ...)으로 값을 제공하는 것은 잠재적 인 오류와 마찬가지로 그것이 가리키는 객체를 잃을 수 있습니다.
OutOfMemoryError
new를 호출하고 할당자가 요청 된 셀을 할당 할 수없는 경우 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는 내부적으로 참조에 의한 전달을 사용합니다.
아니에요.
Java에는 포인터가 없습니다. 당신이 경우 정말 원하는 당신은 반사 같은 주위를 구축하여 그들을 모방을 시도 할 수 있지만 모든 것 복잡성 의 없음과 포인터의 장점을 .
Java에는 포인터가 필요하지 않기 때문에 포인터가 없습니다. 이 질문에서 어떤 종류의 답변을 원했습니까? 즉, 무언가에 사용할 수 있기를 바랐습니까, 아니면 그냥 호기심 이었습니까?
자바의 모든 객체는 프리미티브를 제외한 참조 복사에 의해 함수로 전달됩니다.
실제로 이것은 개체 자체의 복사본이 아닌 원래 개체에 대한 포인터 복사본을 보내는 것을 의미합니다.
이것을 이해하기위한 예제를 원한다면 코멘트를 남겨주세요.
swap
두 개체를 교환하는 Java 함수를 작성할 수 없습니다 .
Godfrey Nolan의 Decompiling Android라는 책에서 발췌
보안은 포인터가 Java에서 사용되지 않기 때문에 해커가 응용 프로그램에서 벗어나 운영 체제로 침입 할 수 없도록 지정합니다. 포인터가 없다는 것은 다른 것이 (이 경우 JVM) 메모리 할당 및 해제를 처리해야 함을 의미합니다. 메모리 누수도 과거의 일이되어야합니다. 그렇지 않으면 이론이 진행됩니다. C 및 C ++로 작성된 일부 응용 프로그램은 프로그래머가 적절한 시간에 원치 않는 메모리를 확보하는 데주의를 기울이지 않기 때문에 체처럼 메모리를 누출하는 것으로 악명이 높습니다.이를 읽는 사람은 그러한 죄를 범하는 것이 아닙니다. 가비지 수집은 또한 메모리 문제를 디버깅하는 데 소요되는 시간을 줄이면서 프로그래머의 생산성을 높여야합니다.
리터럴에 대한 포인터도 가질 수 있습니다. 직접 구현해야합니다. 전문가에게는 매우 기본입니다.). int / object / long / byte 배열을 사용하고 포인터를 구현하기위한 기본 사항이 있습니다. 이제 모든 int 값은 해당 배열 int []에 대한 포인터가 될 수 있습니다. 포인터를 증가시킬 수 있고, 포인터를 감소시킬 수 있으며, 포인터를 곱할 수 있습니다. 실제로 포인터 산술이 있습니다! 이것이 1000 개의 int 속성 클래스를 구현하고 모든 속성에 적용되는 일반 메서드를 갖는 유일한 방법입니다. int [] 대신 byte [] 배열을 사용할 수도 있습니다.
그러나 Java가 참조로 리터럴 값을 전달할 수 있기를 바랍니다. 라인을 따라 뭔가
//(* telling you it is a pointer)
public void myMethod(int* intValue);