Java의 변수: 변수는 무엇이며 어떻게 사용됩니까?
출처:
Hackernoon Java에는 프로그램에서 선언된 위치에 따라 네 가지 유형의 변수가 있습니다. 오늘은 각 유형의 예와 차이점을 알아보겠습니다. 1. 인스턴스 변수 또는
인스턴스 필드는 static 키워드 없이 클래스 내부에 선언되지만 메서드, 생성자 또는 코드 블록 외부에 선언된 변수입니다. 이러한 변수는 클래스 내 어디에서나 선언될 수 있습니다.
public ,
private ,
protected 또는
default (키워드 아님) 와 같은 액세스 한정자를 사용하거나 사용하지 않고 선언할 수 있습니다 .
public class MyClass {
private String instanceField1;
public MyClass(){}
public int anotherInstanceField2;
public void setInstanceField(String parameterVariable) {...}
boolean instanceField3;
public static void main(String[] args) {
System.out.println("field 1 value: " + instanceField1);
System.out.println("field 2 value: " + anotherInstanceField2);
System.out.println("field 3 value: " + instanceField3);
}
}
인스턴스 필드에 선언 시 값이 할당되지 않은 경우 기본 유형(예: int ,
boolean ,
long ,
float ) 이면 기본값 0이 할당되고 기본 유형이 아닌 경우
null이 할당됩니다. 예를 들어 (
String ,
Integer ,
AnyClass ). 선언된 클래스에서 생성된 객체의 인스턴스에 속하기 때문에 필드 또는 인스턴스 변수라고 합니다.
public Main {
public static void main(String[] args) {
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1.anotherInstanceField2 = 11;
obj2.anotherInstanceField2 = 33;
System.out.println(obj1.anotherInstanceField2);
System.out.println(obj2.anotherInstanceField2);
}
}
따라서 위의 코드 조각에서 볼 수 있듯이 각 인스턴스 필드는 해당 개체에 대해 고유합니다. 여기에서
obj1 과
obj2 는 각각의 인스턴스 필드에 고유한 값이 할당되어 있습니다.
2. 클래스 필드 또는
정적 필드는 static 키워드 로 선언된 필드입니다 . 클래스 내부에서 선언되지만 메서드, 생성자 또는 코드 블록 외부에서 선언됩니다.
또한 public ,
private ,
protected 또는
default (키워드 아님)와 같은 액세스 한정자를 사용하거나 사용하지 않고 클래스 내의 어느 위치에서나 선언할 수 있습니다 .
public class MyClass {
public static String staticField;
public MyClass(){}
}
class Main {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.staticField
MyClass.staticField = "I am a static field";
System.out.println(MyClass.staticField);
}
}
위의 코드 조각에 표시된 것처럼 정적 필드는 해당 클래스를 통해서만 액세스할 수 있으며 객체에서는 액세스할 수 없습니다. 3.
매개변수 또는
인수 변수는 메소드 시그니처의 여는 중괄호와 닫는 중괄호 사이에 있는 메소드 구문 내에서 선언된 변수입니다. 값이나 객체를 메소드에 전달하는 데 사용됩니다.
public class MyClass {
public String instanceField;
public MyClass(){}
public void setInstanceField(String parameterVariable) {
instanceField = parameterVariable;
}
}
class Main {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.setInstanceField("From a parameter variable");
System.out.println(obj.instanceField);
}
}
4.
지역 변수는 메소드나 코드 블록 내에서 선언된 변수입니다(예:
if 문 블록 ,
for 루프 ,
while 루프 , switch 문 블록 등).
public Main {
public static void main(String[] args) {
MyClass obj1 = new MyClass();
int id = 1;
if (id > 1) {
String tempName = "Austin";
}
}
}
이 코드에서는 일부 변수에 참조가 사용되는 것을 볼 수 있지만 로컬 변수
id는 참조 변수로 언급되지 않았습니다. 기본이 아닌 모든 변수는 참조 변수입니다. 예를 들어
obj1 은 MyClass 유형의 변수 이고
tempName 은 String 유형의 변수 이며 여기서 두 유형 모두 기본 유형이 아닙니다. 이 경우
id 는 기본 데이터 유형인
int 유형의 변수입니다 . 따라서 비참조변수이다.
Java의 직렬화 및 역직렬화에 대해 알아야 할 5가지 사항
출처:
Devgenius 이 튜토리얼을 통해 직렬화 및 역직렬화가 작동하는 방식에 대한 지식을 향상시킬 수 있습니다. Java의 직렬화는 기존 객체를 바이트 스트림으로 변환하는 데 도움이 됩니다. 반대로 역직렬화는 바이트 스트림을 객체로 만듭니다. Java에서 직렬화 및 역직렬화를 사용하면 객체에 대한 정보를 한 JVM에서 다른 JVM으로 전송할 수 있습니다.
#1 직렬화
자세히 알아보기 전에 SerializeUtils.java 및
Person.java 클래스를 살펴보겠습니다 . 여기서는 특정 예제를 사용하여 직렬화 및 역직렬화를 수행하는 데 도움이 됩니다.
SerializeUtils.java
package com.techteam.serialization;
import java.io.*;
public class SerializeUtils {
public static <T> void serialize(T input, String fileName) throws IOException {
FileOutputStream file = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(file);
out.writeObject(input);
out.close();
file.close();
}
public static <T> T deserialize(String fileName) throws IOException, ClassNotFoundException {
FileInputStream file = new FileInputStream(fileName);
ObjectInputStream in = new ObjectInputStream(file);
T result = (T) in.readObject();
return result;
}
public static void externalSeialize(Externalizable e, String fileName) throws IOException {
FileOutputStream file = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(file);
e.writeExternal(out);
out.close();
file.close();
}
public static void externalDeseialize(Externalizable e, String fileName) throws IOException, ClassNotFoundException {
FileInputStream file = new FileInputStream (fileName);
ObjectInputStream in = new ObjectInputStream (file);
e.readExternal(in);
in.close();
file.close();
}
}
Person.java
package com.techteam.serialization;
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
앞서 언급했듯이 직렬화는 객체를 바이트 스트림으로 변환하는 데 도움이 됩니다. 이는 객체에 대한 모든 정보(메서드, 속성, 데이터 등)도 바이트 스트림으로 변환된다는 의미입니다. 다음은 객체가 직렬화되는 방법의 예입니다.
package com.techteam.serialization;
import java.io.IOException;
public class SerializationMain {
public static void main(String[] args) throws IOException {
Person p = new Person();
p.setId(1);
p.setName("Tech team members");
p.setAge(20);
SerializeUtils.serialize(p, "/person.txt");
}
}
직렬화 프로세스 후에는 다음 내용이 포함된 파일이 생성됩니다.
#2 역직렬화
이전 예제에서 객체를 직렬화하여 바이트 스트림을 생성했다면 이제 역직렬화를 사용하여 객체로 돌아가는 방법을 살펴보겠습니다.
package com.techteam.serialization;
import java.io.IOException;
public class DeserializationMain {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Person p = SerializeUtils.deserialize("/person.txt");
System.out.println("Person data:");
System.out.println(p.getId());
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
역직렬화 프로세스 이후의 데이터는 다음과 같습니다.
#3 직렬 버전 UID
SerialVersionUID는 직렬화 및 역직렬화 프로세스의 각 버전에 대한 고유 식별 번호를 의미합니다. 이 숫자는 직렬화된 객체와 역직렬화된 객체 모두 호환 가능한 클래스를 사용하는지 확인하는 데 사용됩니다.
Person.java 의 경우 serialVersionUID를 2로 늘리고 싶습니다. person.txt 파일을 역직렬화한 후의 출력을 살펴보겠습니다.
#4 키워드 일시적
직렬화 및 역직렬화 과정에서 개체에 대한 모든 정보를 직렬화할 필요가 없는 경우가 있습니다. 변수에 대해 임시 프로세스를 사용하면 직렬화되는 개체에서 해당 변수를 무시할 수 있습니다. 아래 예는 이를 보다 명확하게 이해하는 데 도움이 됩니다.
package com.techteam.serialization;
import java.io.IOException;
import java.io.Serializable;
public class PersonWithTransient implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private transient int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
PersonWithTransient p = new PersonWithTransient();
p.setId(2);
p.setName("Tech team members(transient)");
p.setAge(50);
SerializeUtils.serialize(p, "/person_transient.txt");
PersonWithTransient deserializeP = SerializeUtils.deserialize("/person_transient.txt");
System.out.println("Person without transient data:");
System.out.println(deserializeP.getId());
System.out.println(deserializeP.getName());
System.out.println(deserializeP.getAge());
}
}
위 코드에서는 age 변수 에
임시 키워드를 사용했습니다 . 이것이 직렬화 및 역직렬화 프로세스 후에 얻은 결과입니다.
#5 외부화 가능한 인터페이스
Java에서는 직렬화 및 역직렬화 프로세스를 사용자 정의하려는 경우 전환 프로세스를 사용하여 직렬화 및 역직렬화 프로세스에 필요하지 않은 변수를 무시할 수 있습니다.
성능을 단순화하고 향상시키는 또 다른 방법은 직렬화 가능 인터페이스 대신
외부화 가능 인터페이스를 사용하는 것입니다 . 예를 살펴보겠습니다:
package com.techteam.serialization;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class PersonExternalizable implements Externalizable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.name);
out.writeInt(this.age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.name = in.readUTF();
this.age = in.readInt();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
PersonExternalizable p = new PersonExternalizable();
p.setId(3);
p.setName("Tech team members(Externalizable)");
p.setAge(30);
SerializeUtils.externalSeialize(p, "/person_externalizable.txt");
PersonExternalizable deserializeP = new PersonExternalizable();
SerializeUtils.externalDeseialize(deserializeP, "/person_externalizable.txt");
System.out.println("Person data:");
System.out.println(deserializeP.getId());
System.out.println(deserializeP.getName());
System.out.println(deserializeP.getAge());
}
}
보시다시피,
외부화 가능을 사용하면 사용자 정의 논리를 쉽게 작성하고 변수를 무시할 수 있으며
직렬화 가능을 사용하는 것보다 더 나은 성능을 얻을 수 있습니다 . 이제 출력을 살펴보겠습니다.
결론
이 기사를 통해 Java에서 직렬화 및 역직렬화가 어떻게 작동하는지 명확하게 이해했으며 위의 예제가 향후 실제로 도움이 될 수 있기를 바랍니다.
GO TO FULL VERSION