Старый пост я знаю. Независимо от того, какая ориентация может быть или поменялась местами и т. Д. Я разработал эту функцию, которая используется для установки устройства в правильную ориентацию без необходимости знать, как на устройстве организованы портретные и альбомные функции.
private void initActivityScreenOrientPortrait()
{
// Avoid screen rotations (use the manifests android:screenOrientation setting)
// Set this to nosensor or potrait
// Set window fullscreen
this.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
DisplayMetrics metrics = new DisplayMetrics();
this.activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Test if it is VISUAL in portrait mode by simply checking it's size
boolean bIsVisualPortrait = ( metrics.heightPixels >= metrics.widthPixels );
if( !bIsVisualPortrait )
{
// Swap the orientation to match the VISUAL portrait mode
if( this.activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT )
{ this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }
else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ); }
}
else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); }
}
Работает как шарм!
Рассмотрим пример из реального мира:
public class Dog extends Animal
Все собаки - животные, но не все животные - собаки. Следовательно ...
public class Cat extends Animal
Заклинание животного к собаке может быть выполнено только в том случае, если рассматриваемое животное действительно является собакой. В противном случае это заставило бы Вселенную вывести свойства, уникальные для собаки (виляние хвостом, лай и т. Д.), На Животное. Этим животным вполне может быть кошка с уникальными для нее свойствами (мурлыканье, строгий режим самоочистки и т. Д.). Если приведение невозможно, тогда во время выполнения генерируется исключение ClassCastException.
Никто не хочет, чтобы собака мурлыкала.
((M) k) .getClass () дает K. Почему это? Он был преобразован в более общий M!
Вы преобразовали k в M, но все классы имеют метод getClass (). Класс k всегда K, независимо от того, указали ли вы его ссылку на M или нет. Если вы примените Dog к Animal и спросите его, что это за животное, оно все равно ответит, что это собака.
Фактически, приведение к суперклассу излишне. Собака уже является животным, и у нее есть все приемы животного, а также свои собственные. Многие инструменты анализа кода, такие как FindBugs, будут уведомлять вас об избыточных приведениях, чтобы вы могли их удалить.
Предположим, у меня есть метод doIt (), реализованный как в M, так и в K. Выполнение
((M) k) .doIt ( );
дает M или K doIt ()?
K doIt () по тем же причинам, что и выше. Приведение работает со ссылкой; он не преобразует объект в другой тип.
Можете ли вы привести пример того, когда приведение (Dog doggy = (Dog) myAnimal) имеет смысл?
Конечно, может. Представьте себе метод, который получает список животных для обработки. Всех собак нужно выгуливать, и всеми кошками нужно играть с помощью игрушки в форме птицы. Для этого мы вызываем метод takeForWalk ()
, который существует только в Dog, или метод play ()
, который существует только в Cat.
public void amuseAnimals( List<Animal> animals ) {
for ( Animal animal : animals ) {
if ( animal instanceof Dog ) {
Dog doggy = (Dog)animal;
doggy.takeForWalk( new WalkingRoute() );
} else if ( animal instanceof Cat ) {
Cat puss = (Cat)animal;
puss.play( new BirdShapedToy() );
}
}
}
Чтобы добавить к ответу Фредерика, приведение объекта к чему-то не меняет его тип. Кроме того, объект может быть приведен только к тому типу, которым он уже является (компилятор просто не знает в этот момент) Вот почему невозможные преобразования никогда не будут приняты:
Integer i = (Integer) new String();
не будет компилироваться, потому что компилятор знает, что это невозможно.
Просто потому, что E расширяет C, C не становится E ... E, с другой стороны, является C
Edit: Чтобы развернуть комментарий Марка ниже ... Только потому, что каждая женщина - человек, не все люди - женщины. Все люди разделяют "человеческий интерфейс" ногами, руками, лицами и т. Д. Женщины расширяют его функциональностью, которая возвращает хорошие чувства, когда вы даете алмазы и золото.
Двойное преобразование int => даже не связано, поскольку это не так. приведение класса, но преобразование, указывающее компилятору хранить все, что находится в x, в y (что оказывается двойным).
((M) k) .getClass () дает K.
, потому что k по-прежнему является K, даже если вы примените его к M или объекту (или чему-то еще, что это может быть).
Edit: Я думаю, что путаница здесь в том, что вы считаете, что k "становится" M, когда вы его разыгрываете , это не т. Вы просто относитесь к нему как к M. Если вы спросите кого-то, кто является «владельцем собаки», что это за порода, он не вернет «Это собака», причина просто в том, что метод getBreedName (), вероятно, был переопределен в подклассе LabradorOwner для возврата » Лабрадор ». То же самое и с getClass (), он вернет класс реализации. Это будет не M, а K, который также будет M просто потому, что K расширяет M.
Вы не можете приводить объекты в Java.
Вы можете приводить ссылки в Java.
Приведение ссылки ничего не меняет в объекте, на который она ссылается. Он создает только ссылку другого типа, указывающую на тот же объект, что и исходная ссылка.
Приведение примитивных значений отличается от приведения ссылок. В этом случае значения изменяются .
the int
/double
is unrelated; that is a conversion, not a cast - there is no relationship between int
and double
.
Re the question; a type's object is fixed at creation. An object that is a C
is not (and can never be) an E
. However, you can treat an E
as a C
, since inheritance represents "is a". For example:
E e = new E();
C c = e;
Here we still only have one object - simply that the c
variable thinks of it as a C
, so won't expose methods specific to E
(even though the object is an E
).
If we then add:
E secondE = (E) c;
This is a type check; again, we haven't changed the object, but to put c
into an E
variable requires us to prove to the compiler/runtime that it really is an E
. We didn't need this in the first example as it can already prove that any E
is also a C
.
Likewise, with the getClass()
- all the cast does is change how the compiler thinks of the object; you haven't changes the object itself. It is still a K
.
You need to separate variables from objects. The cast is talking about the variables; they don't change the object.
Что касается первого вопроса, вы не можете преобразовать суперкласс в подкласс, потому что подкласс добавляет элементы, которых у суперкласса нет. Как компилятор должен знать, какие значения вводить при преобразовании? По сути, E - это C, но C не является E.
getClass () получает тип объекта в памяти. Приведение к M просто скрывает тот факт, что это K, и не меняет базовый объект.
((M) k) .getClass () дает K. Почему это так? Он был преобразован в более общий M!
Полезная аналогия (которую я получил с сайта Билла Веннерса artima.com), которая может помочь устранить путаницу, заключается в том, что разница между классами и объектами подобна разнице между чертежами архитектора. и собственно построенный дом. План существует на бумаге и является концепцией, а дом существует в реальной жизни. Вы можете построить более одного дома по одному и тому же проекту.
Как это имеет отношение к этому вопросу? Допустим, есть план McMansion
и план McMansionWithHeatedPool
. McMansionWithHeatedPool
является расширением McMansion
с подогреваемым бассейном.
Теперь, если вы видите настоящий McMansionWithHeatedPool
, для этого объекта:
Концептуально (то есть, если вы посмотрите на чертежи архитектора), вы увидите, что McMansionWithHeatedPool
явно также McMansion
. Следовательно, апкаст разрешен. (По той же причине объект McMansion
не может быть преобразован в тип McMansionWithHeatedPool
: нет бассейна с подогревом!)
(( McMansion
) k). getClass () дает McMansionWithHeatedPool
, потому что k по-прежнему является McMansionWithHeatedPool
. Приведение типа выполняется для выражения, а не для объекта.
«Если компилятор рассматривает его как M, он должен выполнять методы M».
Компилятор обрабатывает ссылку как M. Экземпляр , на который указывает ссылка, имеет тип K, а не M. Вы не можете привести ссылку и предположить, что это означает, что экземпляр внезапно изменить поведение. Компилятор должен убедиться, что метод, который вы вызываете для указанной ссылки, существует. Это не имеет ничего общего с тем, какая реализация вызывается, только то, что реализация действительно существует.