Перейти к содержимому

Как узнать класс объекта с

  • автор:

Как узнать класс объекта java

Чтобы узнать класс объекта в Java, можно использовать метод getClass() :

Object obj = new String("Hello, World!"); Class cls = obj.getClass(); System.out.println("Class of obj: " + cls.getName()); 

В этом примере мы создаем объект String , затем вызываем метод getClass() , чтобы получить класс этого объекта, и, наконец, используем метод getName() , чтобы получить имя класса. Результатом будет:

Class of obj: java.lang.String 

Метод getClass() возвращает объект типа Class , который содержит информацию о классе объекта. Мы можем использовать этот объект для получения информации о классе, такой как имя, модификаторы доступа, поля, методы и т.д.

Оператор typeid

Оператор typeid позволяет определить тип объекта во время выполнения.

Результатом typeid является const type_info& . Значение является ссылкой на type_info объект, представляющий идентификатор типа или тип выражения, в зависимости от того, какая форма typeid используется. Дополнительные сведения см. в разделе type_info класса.

Оператор typeid не работает с управляемыми типами (абстрактными деклараторами или экземплярами). Сведения о получении Type указанного типа см. в разделе typeid.

Оператор typeid выполняет проверка во время выполнения при применении к l-значению типа полиморфного класса, где истинный тип объекта не может быть определен статическими сведениями. К таким случаям относятся следующие.

  • Ссылка на класс
  • Указатель, разыменовывая с помощью *
  • Подстрочный указатель ( [ ] ). (Небезопасно использовать подстрок с указателем на полиморфный тип.)

Если выражение указывает на тип базового класса, но объект фактически является типом, производным от этого базового класса, type_info ссылка на производный класс является результатом. Выражение должно указывать на полиморфный тип (класс с виртуальными функциями). В противном случае результатом является type_info статический класс, на который ссылается выражение. Кроме того, указатель должен быть разоменовывлен таким образом, чтобы используемый объект указывал на него. Без разыменовки указателя результатом будет type_info указатель, а не то, что он указывает. Например:

// expre_typeid_Operator.cpp // compile with: /GR /EHsc #include #include class Base < public: virtual void vvfunc() <>>; class Derived : public Base <>; using namespace std; int main() < Derived* pd = new Derived; Base* pb = pd; cout 

Если выражение расшифровывает указатель и значение указателя равно нулю, typeid вызывает исключение bad_typeid. Если указатель не указывает на допустимый объект, __non_rtti_object создается исключение. Он указывает на попытку проанализировать RTTI, которая вызвала ошибку, так как объект каким-то образом недопустим. (Например, это плохой указатель или код не компилировался с помощью /GR.

Если выражение не является указателем, а не ссылкой на базовый класс объекта, результатом является type_info ссылка, представляющая статический тип выражения. Статический тип выражения относится к типу выражения, известному во время компиляции. Семантика исполнения игнорируется при оценке статического типа выражения. Кроме того, ссылки по возможности игнорируются при определении статического типа выражения:

// expre_typeid_Operator_2.cpp #include int main() < typeid(int) == typeid(int&); // evaluates to true >

typeid также можно использовать в шаблонах для определения типа параметра шаблона:

// expre_typeid_Operator_3.cpp // compile with: /c #include template < typename T >T max( T arg1, T arg2 ) < cout arg2 ? arg1 : arg2 ); > 

Object. Get Type Метод

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Возвращает объект Type для текущего экземпляра.

public: Type ^ GetType();
public Type GetType ();
member this.GetType : unit -> Type
Public Function GetType () As Type
Возвращаемое значение

Точный тип текущего экземпляра в среде выполнения.

Примеры

В следующем примере кода показано, что GetType возвращает тип среды выполнения текущего экземпляра.

using namespace System; public ref class MyBaseClass <>; public ref class MyDerivedClass: MyBaseClass<>; int main() < MyBaseClass^ myBase = gcnew MyBaseClass; MyDerivedClass^ myDerived = gcnew MyDerivedClass; Object^ o = myDerived; MyBaseClass^ b = myDerived; Console::WriteLine( "mybase: Type is ", myBase->GetType() ); Console::WriteLine( "myDerived: Type is ", myDerived->GetType() ); Console::WriteLine( "object o = myDerived: Type is ", o->GetType() ); Console::WriteLine( "MyBaseClass b = myDerived: Type is ", b->GetType() ); > /* This code produces the following output. mybase: Type is MyBaseClass myDerived: Type is MyDerivedClass object o = myDerived: Type is MyDerivedClass MyBaseClass b = myDerived: Type is MyDerivedClass */ 
using System; public class MyBaseClass < >public class MyDerivedClass: MyBaseClass < >public class Test < public static void Main() < MyBaseClass myBase = new MyBaseClass(); MyDerivedClass myDerived = new MyDerivedClass(); object o = myDerived; MyBaseClass b = myDerived; Console.WriteLine("mybase: Type is ", myBase.GetType()); Console.WriteLine("myDerived: Type is ", myDerived.GetType()); Console.WriteLine("object o = myDerived: Type is ", o.GetType()); Console.WriteLine("MyBaseClass b = myDerived: Type is ", b.GetType()); > > // The example displays the following output: // mybase: Type is MyBaseClass // myDerived: Type is MyDerivedClass // object o = myDerived: Type is MyDerivedClass // MyBaseClass b = myDerived: Type is MyDerivedClass 
type MyBaseClass() = class end type MyDerivedClass() = inherit MyBaseClass() let myBase = MyBaseClass() let myDerived = MyDerivedClass() let o: obj = myDerived let b: MyBaseClass = myDerived printfn $"mybase: Type is " printfn $"myDerived: Type is " printfn $"object o = myDerived: Type is " printfn $"MyBaseClass b = myDerived: Type is " // The example displays the following output: // mybase: Type is MyBaseClass // myDerived: Type is MyDerivedClass // object o = myDerived: Type is MyDerivedClass // MyBaseClass b = myDerived: Type is MyDerivedClass 
' Define a base and a derived class. Public Class MyBaseClass End Class Public Class MyDerivedClass : Inherits MyBaseClass End Class Public Class Test Public Shared Sub Main() Dim base As New MyBaseClass() Dim derived As New MyDerivedClass() Dim o As Object = derived Dim b As MyBaseClass = derived Console.WriteLine("base.GetType returns ", base.GetType()) Console.WriteLine("derived.GetType returns ", derived.GetType()) Console.WriteLine("Dim o As Object = derived; o.GetType returns ", o.GetType()) Console.WriteLine("Dim b As MyBaseClass = derived; b.Type returns ", b.GetType()) End Sub End Class ' The example displays the following output: ' base.GetType returns MyBaseClass ' derived.GetType returns MyDerivedClass ' Dim o As Object = derived; o.GetType returns MyDerivedClass ' Dim b As MyBaseClass = derived; b.Type returns MyDerivedClass 

Комментарии

Так как System.Object является базовым классом для всех типов в системе GetType типов .NET, метод можно использовать для возврата Type объектов, представляющих все типы .NET. .NET распознает следующие пять категорий типов:

  • Классы, производные от System.Object,
  • Типы значений, производные от System.ValueType.
  • Интерфейсы, производные от System.Object начиная с платформа .NET Framework 2.0.
  • Перечисления, производные от System.Enum.
  • Делегаты, производные от System.MulticastDelegate.

Для двух объектов x , y имеющих одинаковые типы среды выполнения, Object.ReferenceEquals(x.GetType(),y.GetType()) возвращает . true В следующем примере используется GetType метод с методом , ReferenceEquals чтобы определить, относится ли одно числовое значение к тому же типу, что и два других числовых значения.

int n1 = 12; int n2 = 82; long n3 = 12; Console.WriteLine("n1 and n2 are the same type: ", Object.ReferenceEquals(n1.GetType(), n2.GetType())); Console.WriteLine("n1 and n3 are the same type: ", Object.ReferenceEquals(n1.GetType(), n3.GetType())); // The example displays the following output: // n1 and n2 are the same type: True // n1 and n3 are the same type: False 
open System let n1 = 12 let n2 = 82 let n3 = 12L printfn $"n1 and n2 are the same type: " printfn $"n1 and n3 are the same type: " // The example displays the following output: // n1 and n2 are the same type: True // n1 and n3 are the same type: False 
Module Example Public Sub Main() Dim n1 As Integer = 12 Dim n2 As Integer = 82 Dim n3 As Long = 12 Console.WriteLine("n1 and n2 are the same type: ", Object.ReferenceEquals(n1.GetType(), n2.GetType())) Console.WriteLine("n1 and n3 are the same type: ", Object.ReferenceEquals(n1.GetType(), n3.GetType())) End Sub End Module ' The example displays the following output: ' n1 and n2 are the same type: True ' n1 and n3 are the same type: False 

Чтобы определить, является ли объект определенным типом, можно использовать ключевое слово или конструкцию сравнения типов языка. Например, можно использовать конструкцию TypeOf…Is в Visual Basic или ключевое is слово в C#.

Метод GetType наследуется всеми типами, производными от Object. Это означает, что в дополнение к использованию ключевого слова сравнения собственного языка можно использовать GetType метод для определения типа конкретного объекта, как показано в следующем примере.

object[] values = < (int) 12, (long) 10653, (byte) 12, (sbyte) -5, 16.3, "string" >; foreach (var value in values) < Type t = value.GetType(); if (t.Equals(typeof(byte))) Console.WriteLine("is an unsigned byte.", value); else if (t.Equals(typeof(sbyte))) Console.WriteLine(" is a signed byte.", value); else if (t.Equals(typeof(int))) Console.WriteLine(" is a 32-bit integer.", value); else if (t.Equals(typeof(long))) Console.WriteLine(" is a 64-bit integer.", value); else if (t.Equals(typeof(double))) Console.WriteLine(" is a double-precision floating point.", value); else Console.WriteLine("'' is another data type.", value); > // The example displays the following output: // 12 is a 32-bit integer. // 10653 is a 32-bit integer. // 12 is an unsigned byte. // -5 is a signed byte. // 16.3 is a double-precision floating point. // 'string' is another data type. 
let values: obj[] = [| 12; 10653L; 12uy -5y; 16.3; "string" |] for value in values do let t = value.GetType() if t.Equals typeof then printfn $" is an unsigned byte." elif t.Equals typeof then printfn $" is a signed byte." elif t.Equals typeof then printfn $" is a 32-bit integer." elif t.Equals typeof then printfn $" is a 64-bit integer." elif t.Equals typeof then printfn $" is a double-precision floating point." else printfn $"'' is another data type." // The example displays the following output: // 12 is a 32-bit integer. // 10653 is a 32-bit integer. // 12 is an unsigned byte. // -5 is a signed byte. // 16.3 is a double-precision floating point. // 'string' is another data type. 
Module Example Public Sub Main() Dim values() As Object = < 12, CLng(10653), CByte(12), CSbyte(-5), 16.3, "string" >For Each value In values Dim t AS Type = value.GetType() If t.Equals(GetType(Byte)) Console.WriteLine(" is an unsigned byte.", value) ElseIf t.Equals(GetType(SByte)) Console.WriteLine(" is a signed byte.", value) ElseIf t.Equals(GetType(Integer)) Console.WriteLine(" is a 32-bit integer.", value) ElseIf t.Equals(GetType(Long)) Console.WriteLine(" is a 64-bit integer.", value) ElseIf t.Equals(GetType(Double)) Console.WriteLine(" is a double-precision floating point.", value) Else Console.WriteLine("'' is another data type.", value) End If Next End Sub End Module ' The example displays the following output: ' 12 is a 32-bit integer. ' 10653 is a 32-bit integer. ' 12 is an unsigned byte. ' -5 is a signed byte. ' 16.3 is a double-precision floating point. ' 'string' is another data type. 

Объект Type предоставляет метаданные, связанные с классом текущего Objectобъекта .

Узнать реальный тип объекта

Предположим, есть тип базовый класс SceneObject и есть производные от него классы. Я хочу хранить массив объектов этого класса, для этого завожу vector < SceneObject*>obj. Добавляю туда некоторые объекты производных классов. А когда достаю их оттуда, я хочу узнать их реальный тип. typeid(obj[i]).name() всегда выдает тип SceneObject*. Как узнать реальный тип объекта?( Или может быть, я все делаю неправильно. Как тогда сделать массив объектов, производных от одного класса, чтобы потом можно было определить какой это объект?

Отслеживать
задан 15 мая 2016 в 9:56
195 1 1 серебряный знак 9 9 бронзовых знаков

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

Информация о типе - это дополнительная информация. Когда у вас есть виртуальные функции - есть и их таблица, которая по сути и есть информацией о конкретном типе.

Без этого надо хранить информацию о типе где-то отдельно.

Но как вы хотите использовать эту информацию? Для чего? Обычно - без виртуальных функций - она попросту бессмысленна.

Кстати, раз уж вы пользуетесь указателями и иерархией классов - то учтите, что с точки зрения безопасности деструктор базового класса должен быть объявлен как виртуальный!

Отслеживать
ответ дан 15 мая 2016 в 10:13
219k 15 15 золотых знаков 120 120 серебряных знаков 230 230 бронзовых знаков

Для определения реального типа объекта вы можете воспользоваться dynamic_cast : TYPE* dynamic_cast (object);

Отслеживать
ответ дан 15 мая 2016 в 10:00
Мстислав Павлов Мстислав Павлов
6,767 2 2 золотых знака 18 18 серебряных знаков 40 40 бронзовых знаков

Для классов, не содержащих виртуальные функции, это не работает( Может быть, можно как-то по-другому?

15 мая 2016 в 10:07
а тут разве не нужно знать к чему кастовать? а вопросе вроде обратный вопрос?
15 мая 2016 в 10:08

Да, тут нужно знать( Но можно сделать иерархию if-else и попробовать поприводить ко всему, при некотором желании(хотя это медленно и неоптимально)

15 мая 2016 в 10:11

Очевидно, что Вы неправильно выводите имя, должно быть так: typeid(*obj[i]).name() , но это будет работать лишь в том случае, когда SceneObject является полиморфным, т.е. содержит хотя бы одну виртуальную функцию. Это требуется потому, что без этого RTTI по классу отсутствует, и оператору typeid просто неоткуда узнать, что же за тип ему реально передан.

Если Вы немного подумаете, то поймёте, что для того, чтобы получить информацию во время исполнения, нужно использовать какие-то средства времени исполнения. В C++ все эти вещи связаны с виртуальностью и ничем другим. Поэтому без полиморфного базового класса, боюсь, Вам задачу не решить.

Что касается правильно/не правильно. Обычно, если появляется задача узнать реальный тип данных, то это на 99% ошибка дизайна. Реальный тип практически никогда знать не нужно, для выполнения конкретной реализации существует полиморфное поведение, то есть виртуальные функции.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *