You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

En enkel og rett frem oversettelse av rpncalc1.py til Java, med en opplisting av de viktigste forskjellene.

Java-pakker og -klasser

Java-kode struktureres i mapper som kalles pakker (eng: package). Pakken må deklareres øverst i fila med en package-setning. Vi velger å legge koden i en mappe/pakke med navn python:

package python; // package declaration

Én fil tilsvarer vanligvis én klasse og navnet må deklareres i en klassedeklarasjon. Konvensjonen er å bruke såkalt camel case, hvor hver del av et sammensatt ord begynner med stor forbokstav og det ellers ikke brukes ordskiller. Derfor bruker vi RPNCalc1 som klassenavn, klassedeklarasjonen blir dermed slik:

class RPNCalc1 {
    ...
}

Alt innholdet forøvrig plasseres mellom krøllparentesene (se nedenfor om bruk av krøllparenteser).

import-setninger og referanser til andre filer

Både Python og Java bruker import-setninger for å referere til andre filer (hhv. moduler eller klasser), men de virker forskjellig. Hvis en i Python skriver import modkjøres mod-modulen, hvis den ikke allerede er kjørt. Etterpå vil en kunne referere til navn på variabler og funksjoner definert i modulen med mod. som prefiks. Hvis en bruker varianten from mod import *, så slipper en også unna å bruke mod.-prefikset. I Java utfører import-setningen ingenting, den brukes bare for å angi fulle klassenavn som du ønsker å kunne referere til med bare det enkle klassenavnet. Hvis en i Java skriver import java.util.List; så vil en lenger ned i fila kunne referere til java.util.List-klassen med bare List.

I vårt program så bruker vi typene java.util.List, java.util.ArrayList og java.util.Scanner, derfor ser import-delen av programmet slik ut:

import java.util.List; // import java.util.List, so it later kan be referenced with just List
import java.util.ArrayList;
import java.util.Scanner;

Forøvrig kan en i Python ha import-setninger hvor som helst, mens en i Java må samle dem under package-deklarasjonen.

Skilletegn

Python klarer seg generelt med færre skilletegn enn Java. Den generelle regelen i Java er at det skal være semikolon (;) etter alle enkle setninger, f.eks. deklarasjoner, tilordninger og import-setninger, men ikke etter kodeblokker. I tillegg bruker en parenteser rundt betingelsen i if- og while-setninger.

Deklarasjon av variabler og funksjoner

I Java må variabler alltid deklareres eksplisitt med en type, før eller idet de tilordnes eller initialiseres med en verdi. Dette sikrer at en alltid vet hva slags type data en variabel kan ha eller referere til, og gjør det vesentlig lettere for både programmerere og verktøy å analysere kode og oppdage feil før kjøring.

operands-variablen er her en liste av desimaltall, og i Java finnes det en standardtype som heter List i java.util-pakken.  Når en bruker såkalte container-klasser, f.eks. lister, sett og dictionaries (kalles map i Java), så må en også oppgi hvilken type elementene har, og her bruker vi desimaltall-typen Double. Deklarasjonen blir dermed i utgangspunktet java.util.List<Double> operands; eller bare List<Double> operands; hvis en har importert java.util.List øverst i fila.

Mens en Python implisitt deklarerer en variabel med en tilordning (initialisering), så er det i Java frivillig (men sterkt anbefalt) å kombinere deklarasjonen med en tilordning (initialisering). operands-variablen initialiseres i koden under til et objekt av typen ArrayList for Double-typen:

    List<Double> operands = new ArrayList<Double>(); // declare and initialise the operands variable

Tilsvarende som variabler, så deklareres også (retur)typen til funksjoner (kalt metoder i Java). Dermed vet hvilken type en får når en kaller metoden. Dersom en metode ikke returnerer en verdi så brukes typen/nøkkelordet void, slik vi gjør under med main-metodene:

    // declare the main method
	void main() { 
		...
    }

Kodeblokker

Mange kontrollstrukturer omslutter en eller flere setninger, også kalt kodeblokker. I Python markeres begynnelsen på en kodeblokk med kolon (:) og linjeskift, og innrykkene på de påfølgende linjene angir hvilke setninger som hører til kodeblokken. I Java tillater de fleste kontrollstrukturer enten enkeltsetninger, eller en blokk som omsluttes med krøllparenteser, altså { }:

        while (true) {
			// code block
			...
			if (Character.isDigit(token.charAt(0))) {
				// code block
				...
            } else {
				// code block
				...
            }
        }

En viktig egenskap til kodeblokker i Java er at de utgjør et eget nivå for lokale variabler. Variabler som defineres innenfor en kodeblokk gjelder derfor kun innenfor denne blokken. Hvis blokken er en del av en løkke, så vil hver runde i løkka starte med blanke variabler.

token-variablen gjelder altså kun inni while-løkka, og verdien overlevere ikke fra runde til runde i løkka. operand-variablen gjelder tilsvarende bare innenfor if-grenen den er deklarert i og forsvinner når denne if-grenen er ferdig utført.

Utskrift til konsollet

I Python brukes print-funksjonen til å skrive tekst til konsollet. Standardoppførselen er å legge til et linjeskift, men dette kan endres ved å gi inn en alternativ endelse med end=. I Java brukes System.out.print for å skrive ut uten linjeskift og System.out.println for å skrive ut med:

            System.out.println(operands);
            System.out.print(" > ");

I Python kan en sette sammen string-verdier med +, og for å sette en tekst sammen med andre typer, f.eks. tall, så må en konvertere med str-funksjonen. I Java skjer denne konverteringen automatisk, så en kan blande alle typer ved string-sammensetning.

Input fra konsollet

I Python brukes raw_input- eller input-funksjonen (merk at disse ble endret fra versjon 2 til 3!) for å lese input fra brukeren. I Java finnes det flere teknikker, men det enkleste er å deklarere en variabel med typen Scanner (objekt av typen java.util.Scanner), initialisere den med new Scanner(System.in) og bruke en av dens next-metoder for å lese input av ønsket type. F.eks. vil scanner.nextLine() lese en hel linje og returnere denne som en String (uten linjeskiftet) og scanner.nextDouble() lese et desimaltall og returnere denne.

        Scanner scanner = new Scanner(System.in); // declare and initialise the scanner variable
        while (true) {
			...
            String token = scanner.nextLine();  // declare and initialise the token variable
			...
        }
		...
		scanner.close(); // always remember to close it, before the block scope ends

Nyttige metoder og funksjoner

Både Python og Java har mange nytte funksjoner/metoder som det er greit å ha oversikt over. Noen funksjoner kalles direkte, mens andre må kalles på et objekt, typisk med med et variabelnavn og punktum foran. F.eks. bruker en i Python len(str) for å finne lengden til en string og str.find(substr) for å finne indeksen til første forekomst av substr i str. Her en liten oversikt over nyttige Java-funksjoner/metoder:

NavnBeskrivelseEksempel
object.equals(other)Returnerer true om object i praksis er lik other, ellers false. Bør brukes for string-objekter"0123".equals("0123") returnerer true
(selv om ikke "0123" == "0123" er true)
string.charAt(pos)Returnerer tegnet i indeks pos i string"0123".charAt(1) returnerer '1'
string.substring(start)Returnerer resten av string fra indeks start"0123".substring(1) returnerer "123"
string.substring(start, end)Returnerer utsnittet av string fra og med start til (men ikke med) end"0123".substring(1,3) returnerer "12"
string.startsWith(prefix)Returnerer true om string starter med prefix, ellers false"0123".startsWith("01") returnerer true
string.endsWith(prefix)Returnerer true om string ender med prefix, ellers false"0123".endsWith("3") returnerer true
Character.isDigit(c)Returnerer true om c er et siffer, ellers falseCharacter.isDigit('0') returnerer true
Integer.valueOf(string)Returnere string konvertert/tolket som et heltall (int)Integer.valueOf("42") returnerer 42
Double.valueOf(string)Returnere string konvertert/tolket som et desimaltall (double)Double.valueOf("3.14") returnerer 3.14

RPNCalc1.java

Og her er all koden:

package python; // package declaration

import java.util.List; // import java.util.List, so it later kan be referenced with just List
import java.util.ArrayList;
import java.util.Scanner;

// declare the RPNCalc1 class
class RPNCalc1 {
    List<Double> operands = new ArrayList<Double>(); // declare and initialise the operands variable

	// declare the main method
    void main() {
        Scanner scanner = new Scanner(System.in); // declare and initialise the scanner variable
        while (true) {
            System.out.println(operands);
            System.out.print(" > ");
            String token = scanner.nextLine();  // declare and initialise the token variable
            if (Character.isDigit(token.charAt(0))) {
                double operand = Double.valueOf(token);
                operands.add(operand);
            } else if (token.equals("exit")) { // in Java there is no elif, you just follow an else with an if
                break;
            } else if (token.equals("+")) {
                operands.add(operands.remove(operands.size() - 1) + operands.remove(operands.size() - 1));
            } else if (token.equals("-")) {
                operands.add(- (operands.remove(operands.size() - 1) - operands.remove(operands.size() - 1)));
            } else {
                System.out.println("Unsupported operator: " + token);
            }
        }
        System.out.println("program exited");
        scanner.close();
    }
    
	// declare the special main method used as entry point for program classes
	public static void main(String[] args) {
        new RPNCalc1().main(); // create program and run its main method
    }
}
  • No labels