Bagaimana cara mencetak objek Java saya tanpa mendapatkan "SomeType @ 2f92e0f4"?
Saya memiliki kelas yang ditentukan sebagai berikut:
public class Person {
private String name;
// constructor and getter/setter omitted
}
Saya mencoba mencetak contoh kelas saya:
System.out.println(myPerson);
tapi aku punya output sebagai berikut: com.foo.Person@2f92e0f4
.
Hal serupa terjadi ketika saya mencoba mencetak larik Person
objek:
Person[] people = //...
System.out.println(people);
Saya mendapatkan hasilnya: [Lcom.foo.Person;@28a418fc
Apa artinya keluaran ini? Bagaimana cara mengubah keluaran ini sehingga berisi nama orang saya? Dan bagaimana cara mencetak koleksi objek saya?
Catatan : ini dimaksudkan sebagai Q&A kanonik tentang subjek ini.
Jawaban
Latar Belakang
Semua objek Java memiliki toString()
metode yang dipanggil saat Anda mencoba dan mencetak objek.
System.out.println(myObject); // invokes myObject.toString()
Metode ini didefinisikan di Object
kelas (superclass dari semua objek Java). The Object.toString()
method mengembalikan string mencari cukup jelek, terdiri dari nama kelas, sebuah @
simbol dan kode hash dari objek dalam heksadesimal. Kode untuk ini terlihat seperti:
// Code of Object.toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Hasil seperti com.foo.MyType@2f92e0f4
itu dapat dijelaskan sebagai:
com.foo.MyType
- nama kelas, yaitu kelas yang adaMyType
di dalam paketcom.foo
.@
- menggabungkan string bersama2f92e0f4
kode hash objek.
Nama kelas array terlihat sedikit berbeda, yang dijelaskan dengan baik di Javadocs for Class.getName()
. Misalnya, [Ljava.lang.String
artinya:
[
- array satu dimensi (sebagai lawan[[
atau[[[
dll.)L
- array berisi kelas atau antarmukajava.lang.String
- jenis objek dalam larik
Menyesuaikan Output
Untuk mencetak sesuatu yang berbeda ketika Anda menelepon System.out.println(myObject)
, Anda harus menimpa para toString()
metode di kelas Anda sendiri. Berikut contoh sederhananya:
public class Person {
private String name;
// constructors and other methods omitted
@Override
public String toString() {
return name;
}
}
Sekarang jika kita mencetak a Person
, kita melihat nama mereka daripada com.foo.Person@12345678
.
Ingatlah bahwa toString()
ini hanyalah salah satu cara untuk mengubah objek menjadi string. Biasanya, keluaran ini harus mendeskripsikan objek Anda secara jelas dan ringkas. Yang lebih baik toString()
untuk Person
kelas kami mungkin:
@Override
public String toString() {
return getClass().getSimpleName() + "[name=" + name + "]";
}
Yang akan dicetak, misalnya Person[name=Henry]
. Itu adalah bagian data yang sangat berguna untuk debugging / pengujian.
Jika Anda ingin fokus hanya pada satu aspek dari objek Anda atau menyertakan banyak format jazzy, Anda mungkin lebih baik untuk mendefinisikan metode terpisah, mis String toElegantReport() {...}
.
Menghasilkan Output secara otomatis
Banyak IDE menawarkan dukungan untuk membuat toString()
metode secara otomatis, berdasarkan kolom di kelas. Lihat dokumen untuk Eclipse dan IntelliJ , misalnya.
Beberapa perpustakaan Java populer juga menawarkan fitur ini. Beberapa contoh termasuk:
@ToString
anotasi dari Project Lombok
Mencetak kelompok objek
Jadi, Anda telah membuat yang bagus toString()
untuk kelas Anda. Apa yang terjadi jika kelas tersebut ditempatkan ke dalam array atau koleksi?
Array
Jika Anda memiliki larik objek, Anda dapat memanggil Arrays.toString()
untuk menghasilkan representasi sederhana dari konten larik. Misalnya, pertimbangkan larik Person
objek ini:
Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(Arrays.toString(people));
// Prints: [Fred, Mike]
Catatan: ini adalah panggilan ke metode statis yang disebut toString()
dalam kelas Array, yang berbeda dengan yang telah kita bahas di atas.
Jika Anda memiliki larik multi-dimensi , Anda dapat menggunakan Arrays.deepToString()
untuk mendapatkan jenis keluaran yang sama.
Koleksi
Sebagian besar koleksi akan menghasilkan keluaran yang cantik berdasarkan pemanggilan .toString()
setiap elemen.
List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));
System.out.println(people);
// Prints [Alice, Bob]
Jadi Anda hanya perlu memastikan elemen daftar Anda mendefinisikan bagus toString()
seperti yang dibahas di atas.
Saya pikir apache menyediakan kelas util yang lebih baik yang menyediakan fungsi untuk mendapatkan string
ReflectionToStringBuilder.toString(object)
Setiap kelas di Java memiliki toString()
metode di dalamnya secara default, yang dipanggil jika Anda meneruskan beberapa objek dari kelas itu ke System.out.println()
. Secara default, panggilan ini mengembalikan kode hash className @ objek itu.
{
SomeClass sc = new SomeClass();
// Class @ followed by hashcode of object in Hexadecimal
System.out.println(sc);
}
Anda dapat mengganti metode toString kelas untuk mendapatkan keluaran yang berbeda. Lihat contoh ini
class A {
String s = "I am just a object";
@Override
public String toString()
{
return s;
}
}
class B {
public static void main(String args[])
{
A obj = new A();
System.out.println(obj);
}
}
Di Eclipse, Pergi ke kelas Anda, Klik kanan-> source-> Generate toString()
;
Ini akan mengganti toString()
metode dan akan mencetak objek dari kelas itu.
Saya lebih suka menggunakan fungsi utilitas yang menggunakan GSON untuk membatalkan serialisasi objek Java menjadi string JSON.
/**
* This class provides basic/common functionalities to be applied on Java Objects.
*/
public final class ObjectUtils {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private ObjectUtils() {
throw new UnsupportedOperationException("Instantiation of this class is not permitted in case you are using reflection.");
}
/**
* This method is responsible for de-serializing the Java Object into Json String.
*
* @param object Object to be de-serialized.
* @return String
*/
public static String deserializeObjectToString(final Object object) {
return GSON.toJson(object);
}
}
Dalam intellij Anda dapat menghasilkan metode toString secara otomatis dengan menekan alt + inset dan kemudian memilih toString () di sini adalah keluaran untuk kelas pengujian:
public class test {
int a;
char b;
String c;
Test2 test2;
@Override
public String toString() {
return "test{" +
"a=" + a +
", b=" + b +
", c='" + c + '\'' +
", test2=" + test2 +
'}';
}
}
Seperti yang Anda lihat, itu menghasilkan String dengan menggabungkan, beberapa atribut kelas, untuk primitif itu akan mencetak nilainya dan untuk jenis referensi itu akan menggunakan jenis kelas mereka (dalam hal ini metode string Test2).
Secara default, setiap Objek di Java memiliki toString()
metode yang menghasilkan ObjectType @ HashCode.
Jika Anda menginginkan informasi yang lebih bermakna maka Anda perlu mengganti toString()
metode di kelas Anda.
public class Person {
private String name;
// constructor and getter/setter omitted
// overridding toString() to print name
public String toString(){
return name;
}
}
Sekarang ketika Anda mencetak objek orang menggunakannya System.out.prtinln(personObj);
akan mencetak nama orang itu bukan nama kelas dan kode hash.
Dalam kasus kedua Anda ketika Anda mencoba untuk mencetak array, itu mencetak [Lcom.foo.Person;@28a418fc
tipe Array dan itu kode hash.
Jika ingin mencetak nama orang, ada banyak cara.
Anda dapat menulis fungsi Anda sendiri yang mengulang setiap orang dan mencetaknya
void printPersonArray(Person[] persons){
for(Person person: persons){
System.out.println(person);
}
}
Anda bisa mencetaknya menggunakan Arrays.toString (). Ini tampaknya yang paling sederhana bagi saya.
System.out.println(Arrays.toString(persons));
System.out.println(Arrays.deepToString(persons)); // for nested arrays
Anda bisa mencetaknya dengan java 8 (menggunakan aliran dan referensi metode).
Arrays.stream(persons).forEach(System.out::println);
Mungkin ada cara lain juga. Semoga ini membantu. :)
Jika Anda langsung mencetak objek apa pun dari Orang, itu akan ClassName@HashCode
ke Kode.
dalam kasus Anda com.foo.Person@2f92e0f4
akan dicetak. Di mana Person
kelas di mana objek dimiliki dan 2f92e0f4
merupakan kode hash dari Objek.
public class Person {
private String name;
public Person(String name){
this.name = name;
}
// getter/setter omitted
@override
public String toString(){
return name;
}
}
Sekarang jika Anda mencoba menggunakan objek Person
maka itu akan mencetak nama
Class Test
{
public static void main(String... args){
Person obj = new Person("YourName");
System.out.println(obj.toString());
}
}
Jika Anda melihat kelas Object (kelas Induk dari semua kelas di Java) implementasi metode toString () adalah
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
setiap kali Anda mencetak objek apa pun di Java maka toString () akan dipanggil. Sekarang terserah Anda jika Anda mengganti toString () maka metode Anda akan memanggil metode panggilan kelas Object lainnya.
Saya berhasil menyelesaikan ini menggunakan Jackson
di Spring 5. Bergantung pada objek Jackson mungkin tidak berfungsi di semua kasus.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
ObjectMapper mapper = new ObjectMapper();
Staff staff = createStaff();
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);
System.out.println("-------------------------------------------------------------------")
System.out.println(json);
System.out.println("-------------------------------------------------------------------")
hasilnya akan seperti ini
-------------------------------------------------------------------
{
"id" : 1,
"internalStaffId" : "1",
"staffCms" : 1,
"createdAt" : "1",
"updatedAt" : "1",
"staffTypeChange" : null,
"staffOccupationStatus" : null,
"staffNote" : null
}
-------------------------------------------------------------------
Lebih banyak contoh digunakan Jackson
di sini
Anda GSON
juga bisa mencoba . Seharusnya seperti ini:
Gson gson = new Gson();
System.out.println(gson.toJson(objectYouWantToPrint).toString());