Konwersja i rzutowanie typów

Konwersja rozszerzająca

Zdarza się tak, że jeśli w jednej ze zmiennych przechowujemy jakieś dane typu A, to w pewnym momencie potrzebujemy tych samych danych, ale już w typie B. Najprostszy przykład, to taki, w którym mamy liczbę zadeklarowaną jako int, a następnie chcemy ją podzielić przez inną wartość typu int. Wykonujemy w takiej sytuacji dzielenie całkowitoliczbowe, więc część dziesiętna będzie ucięta.

W sytuacji, gdy będziemy przez siebie jednak dzielili wartości różnych typów, np. double przez int, to przed wykonaniem operacji dzielenia wykona się niejawna konwersja rozszerzająca.

Kurs Java

W skrócie, możemy sobie wyobrazić, że przy działaniach matematycznych wszystkie wartości są automatycznie konwertowane przez wirtualną maszynę Javy do najogólniejszego typu. Najogólniejszy typ to ten, przy pomocy którego da się wyrazić obie strony działania.

class Conversions {
    public static void main(String[] args) {
        int a = 5;
        double b = 13.5;
        double c = b / a;
        System.out.println(c);
    }
}

Widzimy to działanie w powyższym przykładzie. Najpierw deklarujemy dwie zmienne a i b , odpowiednio typów int , oraz double . Następnie do zmiennej c przypisujemy wynik działaniab / a. Czego się spodziewać w takiej sytuacji?

java konwersje_1

Przed wykonaniem dzielenia, zmienna a jest konwertowana na typ double . Dzięki temu dzielimy przez siebie tak naprawdę dwie wartości typu double , a nie int i double . W wyniku otrzymamy wartość zmiennoprzecinkową, a nie całkowitoliczbową. Z tego powodu nie możesz zadeklarować typu zmiennej c jako int.

class Conversions {
    public static void main(String[] args) {
        int a = 5;
        double b = 13.5;
        int c = b / a; //BŁĄD!
        System.out.println(c);
    }
}

W powyższym przykładzie próbujemy przypisać do zmiennej c , która jest typu int , wynik ilorazu b/a, którym jest liczba zmiennoprzecinkowa 2.7. W takim przypadku kompilator zaprotestuje.

java incompatybile_types

No dobrze, ale co zrobić, gdy faktycznie potrzebujemy zamienić typ double na int i część dziesiętna nas nie interesuje?

Konwersja zawężająca

Konwersja zawężająca w przeciwieństwie do konwersji rozszerzającej musi być zapisana jawnie. Możemy wymusić konwersję z jednego typu na inny umieszczając uprzednio w okrągłych nawiasach typ docelowy.

int a = 5;
double b = 13.5;
int c = (int)b/a;

W takiej sytuacji błędu już nie będzie. Jednak musimy zdawać sobie sprawę z tego, że takie postępowanie niesie ze sobą utratę części danych, w tym przypadku ucięcie części ułamkowej. W powyższym przykładzie najpierw następuje dzielenie - otrzymujemy wynik z przecinkiem, a następnie ucięcie (nie zaokrąglenie!) wyniku. Aby otrzymać przybliżoną wartość wyniku należałoby użyć metody Math.round().

Konwersję rozszerzającą, którą pokazałem na początku tego artykułu można także zapisać jawnie:

int a = 5;
double b = 13.5;
double c = b/(double)a;

Na szczęście nie musimy tego zapisywać. Java zrobi to za nas automatycznie.

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.

Poniżej znajdziesz archiwalne wpisy z czasów, gdy strona była jeszcze hobbystycznym blogiem.

Marcin

Mały przykład konwersji typów: kod: public class ASCII{ public static void main(String[] args){ char znak; for(int i = 0; i < 256;){ ++i; znak = (char)i; System.out.print(i+" to "+znak+" "); } } }

Witek

Inny przykład konwersji : public class Demonstracja_Rzutowania { /** * Napisz program przedstawiający niektóre typy rzutowania i konwersji * Wyniki przedstaw na konsoli * */ public static void main(String[] args) { double x = 15.0, y = 5.0; byte b; int i; char ch,ch1; // rzutowanie z double do int i = (int) (x/y); System.out.println("Wynik x/y oraz rzutowania do int to: " + i); // rzutowanie z int do byte i = 129; b = (byte) i; //zakres typu byte : -128 do 127 System.out.println("Wynik rzutowania int do byte to: " + b); // rzutowanie z byte do char b = 67; ch = (char) b; System.out.println("Wynik rzutowania z byte do char to: " + ch); System.out.println(); b = 10; // byte i = b * b; // daje nam typ int System.out.println("Wynik rzutowania jest typu int: " + i); b = 9; b = (byte)(b * b); // rzutujemy spowrotem do typu byte System.out.println("Wynik rzutowania jest teraz typu byte: " + b); ch = 'A'; ch1 = 'h'; ch = (char)(ch + ch1); System.out.println("Wynik rzutowania typu char z powrotem do typu char to: " + ch); } }

NBT

"Rzutowanie (jawna konwersja) Rzutowanie jest w przeciwieństwie do konwersji jawne i mamy na nie wpływ." Czyż nie powinno być: "Rzutowanie jest przeciwieństwem konwersji niejawnej, to znaczy, że mamy na nie wpływ"?

alfa

Dziwne to, taki prosty program : public class KonwersjeAndRzutowanieTypów { public static void main(String[] args) { int a = 3; double b = 10; double c = b / a; System.out.println(c); } } W wyniku dostaje: 3.3333333333333335, skąd ta piątka na końcu, powinny być same trójki :/

Luigi

int c = (int)b/a; "W powyższym przykładzie najpierw następuje dzielenie, a następnie ucięcie(nie zaokrąglenie) wyniku." Nie do końca - operator rzutowania ma wyższy priorytet, więc najpierw następuje zrzutowanie zmiennej b do typu int, a następnie dokonane jest dzielenie liczb całkowitych :)

Jakub

Chcemy zrzutować (a+a*a),(gdzie a jest typu double) na int double a; int c=(int)(a+a*a);// czy może ma być int c=(int)a+(int)a*(int)a;

SAK

Może być i tak i tak, ale wyjdą różne wyniki (przy znaczeniach a double)

ssss

Bardzo przystępnie wytłmaczone ;-)

mario

import java.util.Scanner; public class tablice2 { /** * @param args */ public static void main(String[] args) { System.out.println("Podaj liczbe"); Scanner odczyt = new Scanner(System.in); int n = odczyt.nextInt(); int[] tablica = new int[n]; for(int i = n;i>0;i--){ tablica[i]=i+1; } while(n>0){ System.out.println(tablica[n]); n++; } } } a tak czemu nie dziala?

Marcin Kunert

Na pierwszy rzut oka masz błąd w pętli. Zamiast i- powinno być raczej i--.

lolo

Mario na samej górze i tak samo pod polem do wpisywania komentarzy dostępny jest link do forum JavyStart. Taka mała uwaga tam lepiej jest zadawać pytania razem z kodem gdyż system komentarzy przekształca niektóre rzeczy podczas wysyłania np. cudzysłowie. Co trochę utrudnia pomoc. Dobrze a teraz odnośnie kodu. 1.Jak to Marcin napisał już w linijce for(int i = n;i>0;i–){ powinien być podwójny minus(możliwe, że masz w kodzie ten podwójny minus i tylko system zamienił podczas wysyłania o czym wspomniałem wyżej) 2. Wstaw po linijce int[] tablica = new int[n]; n=n-1; i powinien program już zacząć działać bez zwracania błędów. 3. I mała rada zmień w linii for(int i = n;i>0;i–){ warunek i>0 na i>=0 oraz w linii while(n>0){ warunek n>0 na n>=0 bo wydaje mi się, że o to Ci chodziło.

Chłopek

<pre class="brush: java; gutter: true"> //Chyba nie rozumiesz indeksowania tablic jeszcze ;) for(int i = n;i&gt;0;i- -){ tablica[i-1]=i+1; } while(n&gt;0){ // Też błąd był, bo miałeś n++ co zawsze jest &gt; 0, a po drugie indeksowanie tavblic zaczyna się od ZERA, więc np. w tablicy ośmioelementowej nie będzie indeksu nr 8. Ostatni to 7, a pierwszy to nr 0 ;) System.out.println(tablica[- -n]); }</pre>

Artur

Tyle glow i naprawde nikt nie zauwazyl jeszcze bledu. W pierwszym przykladzie dzielisz a/b i w drugim robisz to samo a/b zamiast b/a, drobny blad ale dla takich laikow jak ja to juz jest klopot z interpretacja.

Artur

Odwrotnie b/a zamiast a/b.

Sławek Ludwiczak

poprawione, dzięki :)