Зачем использовать Upcasting в java?
Я просмотрел большинство газет в сети, но я все еще не могу понять, почему мы должны использовать upcasting.
class Animal
{
public void callme()
{
System.out.println("In callme of Animal");
}
}
class Dog extends Animal
{
public void callme()
{
System.out.println("In callme of Dog");
}
public void callme2()
{
System.out.println("In callme2 of Dog");
}
}
public class UseAnimlas
{
public static void main (String [] args)
{
Dog d = new Dog();
Animal a = (Animal)d;
d.callme();
a.callme();
((Dog) a).callme2();
}
}
вы можете рассмотреть этот пример для upcasting. Какой смысл поднимать здесь тосты? Оба!--1--> и a
дает тот же результат!
9 ответов
в большинстве ситуаций явный апкаст совершенно не нужен и не имеет никакого эффекта.
в вашем примере явный upcast
Animal a = (Animal)d;
можно заменить этот:
Animal a = d; // implicit upcast
цель неявного upcast (для типа объекта Java) - "забыть" статическую информацию о типе, чтобы объект с определенным типом можно было использовать в ситуации, требующей более общего типа. Это влияет на проверку типов во время компиляции, а не выполнения поведение.
(для примитивного типа upcast приводит к преобразованию и в некоторых случаях может привести к потере точности; например long
->float
.)
тем не менее, есть ситуации, когда наличие явного upcast изменяет значение заявления / выражения.
одна ситуация, когда необходимо использовать upcasting в Java, - это когда вы хотите принудительно использовать определенное переопределение метода; например, предположим, что мы перегружены методы:
public void doIt(Object o)...
public void doIt(String s)...
если у меня есть строка, и я хочу вызвать первую перегрузку, а не вторую, я должен сделать это:
String arg = ...
doIt((Object) arg);
связанный случай:
doIt((Object) null);
где код не будет компилироваться без приведения типа. (Я не уверен, что это считается ударом, но вот он в любом случае.)
вторая ситуация включает в себя варадические параметры:
public void doIt(Object... args)...
Object[] foo = ...
doIt(foo); // passes foo as the argument array
doIt((Object) foo); // passes new Object[]{foo} as the argument array.
третья ситуация при выполнении операций с примитивными числами типы; например
int i1 = ...
int i2 = ...
long res = i1 + i2; // 32 bit signed arithmetic ... might overflow
long res2 = ((long) i1) + i2; // 64 bit signed arithmetic ... won't overflow
какая необходимость использовать Upcasting в java?
не уверен, что вы правильно поняли терминологию, но вот цитата уточнения:
upcasting
выполнение приведения из производного класса в более общий базовый класс.
и вот один сценарий, где это действительно имеет значение:
class A {
}
class B extends A {
}
public class Test {
static void method(A a) {
System.out.println("Method A");
}
static void method(B b) {
System.out.println("Method B");
}
public static void main(String[] args) {
B b = new B();
method(b); // "Method B"
// upcasting a B into an A:
method((A) b); // "Method A"
}
}
Upcasting может быть необходимо, когда вы перегружены методы и не хотите, чтобы вызвать специализированный, как aioobe написал. (Вы могли бы назначить новую переменную типа A
вместо того, чтобы есть.)
еще один пример, когда необходим был upcast, включал ?:
оператора, но я не помню его сейчас. И иногда нужно приводит в случае с varargs-методы:
public void doSomething(Object... bla) {}
если мы хотим передать Object[] array
как одиночный параметр (не свои объекты как индивидуальные), мы должны написать либо
doSomething((Object)array);
или
doSomething(new Object[]{array});
Upcasting не имеет абсолютно никакого значения в вашем примере (на самом деле я не могу представить себе ни одного случая, когда у него есть), и его следует избегать, поскольку он только смущает разработчиков. Некоторые IDEs (IntelliJ наверняка) выдадут предупреждение в этой строке и предложат удалить upcasting).
EDIT: этот код дает те же результаты, потому что все методы объекта в Java являются виртуальными, что означает, что целевой метод обнаруживается фактическим типом объекта во время выполнения, а не ссылочным типом. Попробуйте сделать callme()
static и посмотреть, что произойдет.
рассмотрим сценарий, банк-это класс, который предоставляет метод для получения процентной ставки. Но, процентная ставка может отличаться в зависимости от банков. Например, банки SBI, ICICI и AXIS предоставляют 8,4%, 7,3% и 9,7% процентной ставки.
class Bank{
float getRateOfInterest(){return 0;}
}
class SBI extends Bank{
float getRateOfInterest(){return 8.4f;}
}
class ICICI extends Bank{
float getRateOfInterest(){return 7.3f;}
}
class AXIS extends Bank{
float getRateOfInterest(){return 9.7f;}
}
class TestPolymorphism{
public static void main(String args[]){
Bank b;
b=new SBI();
System.out.println("SBI Rate of Interest: "+b.getRateOfInterest());
b=new ICICI();
System.out.println("ICICI Rate of Interest: "+b.getRateOfInterest());
b=new AXIS();
System.out.println("AXIS Rate of Interest: "+b.getRateOfInterest());
}
}
выход:
SBI Rate of Interest: 8.4
ICICI Rate of Interest: 7.3
AXIS Rate of Interest: 9.7
учитывая, что методы объектов Java являются виртуальными по умолчанию, я не вижу никакого использования для upcasting вообще.
где вы видели учебники, сообщающие, что upcasting был необходим? Это первый раз, когда я слышу об этом для Java. (Обратите внимание, что это имеет значение в C# или C++, но это обычно знак плохого дизайна.)
ответы:
- Upcasting происходит неявно каждый раз, когда вы передаете определенный объект методу, принимающему более общий объект. В вашем примере, когда вы передаете собаку методу, принимающему животное, upcasting происходит, хотя вы не делаете этого явно с круглыми скобками.
- как упоминалось другими здесь, в сценариях перегрузки методов, где у вас есть общие и конкретные методы. В вашем примере Представьте, что один метод принимает собаку, а другой - то же имя, что и у животного. Если по какой-то причине вам нужно вызвать общую версию, вам нужно явно передать свой объект.
- явный upcasting может использоваться как форма документации; если в какой-то момент в вашем коде вам больше не нужно ссылаться на собаку как на собаку, но продолжать относиться к ней как к животному, может быть хорошей идеей upcast, чтобы другие разработчики понимали, что происходит.
в этом примере мы создаем два класса Bike и Splendar. Класс Splendar расширяет класс Bike и переопределяет его метод run (). Мы вызываем метод run по ссылочной переменной родительского класса. Поскольку он ссылается на объект подкласса, а метод подкласса переопределяет метод родительского класса, метод подкласса вызывается во время выполнения.
поскольку вызов метода определяется компилятором JVM not, он известен как полиморфизм времени выполнения.
class Bike{
void run(){System.out.println("running");}
}
class Splender extends Bike{
void run(){System.out.println("running safely with 60km");}
public static void main(String args[]){
Bike b = new Splender();//upcasting
b.run();
}
}
простое объяснение Upcasting...
есть 2 класса, один-родительский класс (Demo1), второй-его подкласс (Demo).
-
если метод run1 не имеет параметров, то выход метода будет таким же. Нет Upcasting.
class Demo1{ void run1(){ System.out.println("hello"); } } class Demo extends Demo1 { void run1(){ System.out.println("hello1"); } public static void main(String args[]){ Demo d = new Demo(); d.run1(); Demo1 d1 = new Demo(); d1.run1(); } }
выход д'.run1(); и d1.run1(); будет то же самое.
output: hello1
-
если используется Параметрировать перегрузка использование upcasting хорошо видно. Есть смысл для Upcasting.
class Demo1{ void run1(int a){ System.out.println(a); } } class Demo extends Demo1 { void run1(String b){ System.out.println(b); } public static void main(String args[]){ Demo d = new Demo(); d.run1("b"); Demo1 d1 = new Demo(); d1.run1(2); } }
-
выход д'.run1(); и d1.run1(); будет по-другому.
output: b
2