Как узнать класс объекта 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% ошибка дизайна. Реальный тип практически никогда знать не нужно, для выполнения конкретной реализации существует полиморфное поведение, то есть виртуальные функции.