Inlägg

Inlägg som Teknocide har skrivit i forumet
Av Teknocide
Skrivet av heretic16:

Självklart vet jag hur man importerar en ArrayList till en ArrayList. Men jag lyckas inte som jag vill göra.

Jag har två ArrayListor:

ArrayList<String> item = new ArrayList<String>(); ArrayList<ArrayList<String>> itemList = new ArrayList<ArrayList<String>>();

Så om jag fyller på item med massa värden:

item.add("Hej"); item.add("Då"); item.add("Nej"); item.add("Ja");

Och sedan implementerar jag det in i itemList:

itemList.add(item);

Då har jag placerat en ArrayList i en ArrayList. Problemet är att om jag ska göra detta igen, så måste jag radera item och fylla på den igen. Här kommer problemet: ArrayListor är endast länkar till adresserna. Så raderar jag item så raderar jag ävenitem som finns i itemList.

Fråga:
Finns det inget sätt att radera item utan att itemList ska tappa sitt element?
I så fall måste jag ha flera olika item t.ex.

ArrayList<String> item1 = new ArrayList<String>(); ArrayList<String> item2 = new ArrayList<String>(); ArrayList<String> item3 = new ArrayList<String>();

I detta fall vet jag inte hur många item-listor jag behöver.

Du kan inte radera en ArrayList. Visst, du kan ta bort elementen i den och sätta in nya, men det är fortfarande samma ArrayList. Kan tyckas petigt men det är fundamentalt viktigt att förstå hur det fungerar "under huven"; det är Javas runtime som avgör när en instans (ett objekt som skapats genom "new NågotObjekt(…)") kan raderas ur minnet.

Det vanligaste är att en instans raderas när det inte längre finns kvar några referenser till den. En referens kan hållas i en av dig skapad variabel, som i fallet ArrayList<String> item = new ArrayList<>();, där item rent praktiskt håller värdet av en referens till den nyskapade listan. När du med itemList.add(item); lägger till item i itemList innehåller itemList samma referensvärde som item för stunden håller.

Nu till det intressanta: Om du efter detta allokerar en ny ArrayList till item (alltså item = new ArrayList<String>()), så kommer datan under den förra referensen ligga kvar, orörd, i itemList, medan item nu pekar på ett ny tom lista.

Sammanfattningsvis kan du skapa en praktiskt taget oändlig mängd "item"-listor genom att göra något i stilen

ArrayList<String> item; ArrayList<ArrayList<String>> itemList = new ArrayList<>(); for (int i=0; i<9000; i++) { item = new ArrayList<>(); item.add("Item " + i); itemList.add(item); }

Av Teknocide
Skrivet av Howardtheory:

provade detta nu

shuffle() { let deck = this.deck let current = deck.length let index let temp = deck[current] while(current) { index = Math.floor(Math.random() * current--) temp = deck[index], deck[index] = deck[current] } return deck }

verkar fungera, kan det stämma, ser bra ut nog?

Du sätter aldrig deck[current] till temp

Av Teknocide
Skrivet av videopac:

Haha, tja, har inte sysslat med någondera. Men om de sätts in automagiskt så fungerar det ju tydligen inte helt felfritt... den dumma kompilatorn (eller om det är en interpretator, vad vet jag) fattar ju inte hur man tänkt

Men du använder ju mellanslag, bättre kanske att skriva "Detärjättesköntattslippa..."? Eller är det tänkt så att mellanslag är skiljetecknet men det är även godkänt med mellanslag i en sats? Verkar ju lite snurrigt.

Ja;jag;hade;ju;kunnat;skriva;så;här;också;men;mellanslag;känns;mer;lättillgängligt;:)

Fåniga skämt åsido, det är en smaksak antar jag. Jag tycker det ser elegantare ut utan.

Av Teknocide
Skrivet av videopac:

Fråga från en icke-Java-nisse: varför vill man inte ha semikolon för att avskilja satser?

Skrivet av noMad17:

Aj aj, någon kommer bli förnärmad när du blandar ihop Java med JavaScript vilket är två helt skiljda ting
Utöver personlig preferens vet jag inte varför man skulle välja att inte använda semikolon, särskilt inte om de ändå sätts in automatiskt.
Antagligen kommer man från Python där whitespace är en del av syntaxen och därmed inte behöver semikolon eller måsvingar för att markera avslut eller kodblock.

Det; är; jätteskönt; att; slippa; sätta; semikolon; mellan; saker; som; ändå; är; tydligt; avgränsade.

Av Teknocide
Skrivet av Howardtheory:

Hej!

Börjat skolan här nu och vi ska göra ett kortspel med 52 kort.

Jag har skapat Deck så den genererar ut alla valörer från kort 2 upp till ace vilket ace ska generera värdet 14, vilket jag inte lyckats med just ännu.

men jobbar på shuffle nu med.

shuffle(){ let deck = this.deck let curr = deck.length let ind while(curr){ ind = Math.floor(Math.random() * curr--) [deck[curr], deck[ind]] = [deck[ind], deck[curr]] } return deck }

i denna kurs ska vi jobba med utan ; tecken och när jag inte har ett ;

ind = Math.floor(Math.random() * curr--)

efter denna kod så får jag fel meddelande, "cannot create property 'undefined' on number '"exempelvis" 39'.

Vad är det som gör att i min while loop vägrar fungera utan ; i min kod? vad är det för fel jag gör där? Hur man jag fixa så det fungerar på rätt sett utan ; ?

ha det bra!

ASI (automatic semicolon insertion) fungerar för det mesta bra — jag använder aldrig semikolon i javascript. Ditt kodstycke tolkas däremot så här:

ind = Math.floor(Math.random() * curr--)[deck[curr], deck[ind]] = [deck[ind], deck[curr]]

Du kan lösa det genom att göra platsbytet i tre steg:

1. spara undan värdet på deck[curr] till en temporärvariabel
2. sätt deck[curr] = deck[ind]
3. sätt deck[ind] = temporärvariabel

Skrivet av Zipparn:

Vill du inte ha detta?

while(curr > 0)

0 är ett "falsy" värde i javascript, så när curr blir 0 kommer while-loopen avslutas.

Av Teknocide
Skrivet av heretic16:

Men i Spring ramverk så skriver man in massa text i Java Beans med Spring Context. Jag själv förstår inte.

Jag använder inte Spring (eller Java för den delen, vanligtvis) men är rätt säker på att deras dependency injection-lösning har stöd för så kallad "constructor injection" sedan ett par år tillbaka.

Av Teknocide

Osäker på vad du menar med hur du ska "tolka Java Beans som". En Java Bean är en klass som implementerar Serializable, har tom konstruktor och getters/setters för alla fält. Det är inte mycket att tolka, det bara är så..

edit: Kan ju tillägga att tomma konstruktorer brukar anses dåliga (vilket de är). Moderna ramverk för dependency injection kan injicera konstruktorparametrar så det finns egentligen ingen anledning att skippa konstruktorn, såvida något annat inte tvingar en.

Av Teknocide
Skrivet av heretic16:

Så hur gör jag då? Jag använder inte Maven idag. Men senare ska jag göra det.

Jag använder inte Eclipse men något sånt här kanske fungerar: http://www.oxfordmathcenter.com/drupal7/node/44

Av Teknocide

Du behöver säga åt ditt IDE var dina OJFX-filer ligger. Vanligtvis sköts detta automatiskt genom att hela projektet och dess beroenden sköts av ett byggsystem som Maven eller Gradle, men du kan även säga åt IDE:t att lägga till alla filer som ligger i en viss mapp till ditt projekts "classpath". Efter det är gjort ska det gå att kompilera som normalt.

Av Teknocide

@Alling Tycker det är värt att tillägga att första funktionen i ditt andra exempel också är ren, även om implementationen inte är det.

Av Teknocide
Skrivet av Haider of Sweden:

Jag resonerar better safe than sorry. Jag har ingen aning varför någon skulle tänka sig vilja vara illasinnad, men jag är inte intresserad av att ta reda på det genom min webbsida.

Skrivet av Florrpan:

Du kanske ska lämna tanken helt? Uppenbarligen litar du inte på människor som arbetar med detta på heltid, lol.

Jag tycker OP har en rätt sund inställning. "Oinbjuden" kod har förekommit flera gånger i appar och plugins av olika slag, nu senast var det väl appar på AppStore som visat sig sälja vidare användarinformation till tredjepart? Även öppna bibliotek på exempelvis npm har i vissa fall innehållit skumma saker som kryptovaluta-brytare.

Tillägg kan också av misstag öppna säkerhetshål, beroende på hur eftertänksamma utvecklarna har varit. Jag kan lova att flera stora, omtyckta och välmenande tillägg har brister i koden som tredjepart kan utnyttja för egna syften.

Till OP: Jag brukar se mig runt efter recensioner av tillägg. Ju mer använt ett tillägg är desto troligare blir det att någon annan skulle ha larmat om eventuella säkerhetsbrister eller trojaner. Om leverantören av ett tillägg skyltar med var källkoden finns att hämta eller titta på kan det också vara en indikation på att de inte har något att dölja.

Av Teknocide
Skrivet av heretic16:

Hur tyckte du min javalösning var?

Jag ser inte hur du skulle behöva ha static på fältet. Som sagt, det kommer sluta funka om du använder komponenten två gånger.

Skickades från m.sweclockers.com

Av Teknocide
Skrivet av heretic16:

Okej!

Så hur tycker du att jag ska göra? Getters och setters för att kommunicera mellan klasserna?

Standardsättet är att man vid skapandet av ett nytt objekt skickar med andra komponenter som objektet behöver för att kunna fylla sin funktion (detta kallas dependency injection.).

Exempel:

public class PlotWindow { final private TableView tableView; public PlotWindow(TableView tableView) { this.tableView = tableView; } }

Det går även att skriva sin klass så att beroenden kan sättas i efterhand, men det är inte lika "snyggt"; det är lätt att på något ställe i sin kod glömma skriva plotWindow.setTableView(tableView); och sedan blir det null-fel när programmet kör och plotWindow försöker arbeta med sin TableView.

Dessvärre blir processen för JavaFX krångligare eftersom vyer laddas in dynamiskt från FXML-filer. En snabb googling visar att många använder sig av Springs dependency injection-ramverk, men det verkar snabbt bli överkurs tyvärr :\

Av Teknocide
Skrivet av heretic16:

Intressant! Så hur skulle du ha löst detta? Du menar att static är fusk? Varför är javaprogram fyllda med static här och där?

Static är inte fusk, men det kan användas fel. I ditt exempel blir det fel så snart "klass PlotWindow" används på mer än ett ställe eftersom den andra instansen som skapas kommer skriva över TableViewen. Du kommer alltså inte kunna ha två "PlotWindow"-komponenter igång samtidigt.

Av Teknocide
Skrivet av heretic16:

Inte tableView. Jag gjorde bara en kopia som delar samma adress. Orsaken är att JavaFX tillåter inte statiska fält om det är genererat med Scene Builder. Scene Builder är ett måste för att skapa grafiska applikationer för Andorid och Windows.

Jag ser att du använder static lite här och var. Försök undvika det: static är "anti-OOP", och du behöver inte ha det för någon av dina lösningar. Det verkar därtill som om du inte förstår varför du egentligen använder det, vilket är en indikator på att du med stor sannolikhet använder det fel.

Jag skulle gå så långt som att säga att static utan "final"-modifierare inte bara är onödigt utan också farligt. Ur ett kodperspektiv då, inte för din hälsa (såvida du inte bygger mjukvara för tunga maskiner; då är det farligt för bägge delar.)

Av Teknocide
Skrivet av heretic16:

Betecknar inte this, fältet som används?

this är en referens till instansen som en metod kör på. Egentligen behöver inte this anges i de flesta fall, men brukar anges i konstruktorer då det är vanligt att argumenten har samma namn som fälten i klassen de sätter.

public class Foo { private int x; private static int y = 2; public Foo(int x) { this.x = x; // this används för att skilja på instansens x-värde och konstruktorns argument "x" } public int explicitThisX() { return this.x; } public int implicitThisX() { return x; // ger samma resultat som return this.x då metoden inte har ett eget x-argument } public static int getY() { return Foo.y; // y hämtas direkt från klassen — INTE instansen. Denna metod anropas med "Foo.getY();" } }

Av Teknocide

static säger att klassmedlemmen (fält, metod etc.) inte tillhör en specifik instans av klassen. this.mainStage är egentligen en felaktig referens eftersom this betecknar den instans som metoden körts på.

public class EnKlass { public static String FOO = "Hello"; } // på annan plats: System.out.println(EnKlass.FOO); // pga. static kommer vi åt FOO utan att skapa en instans av "EnKlass"

Av Teknocide
Skrivet av heretic16:

Hej!

Vi säger att jag har en klass A som har en konstruktör med klassen B

public class A { private B b; public A(B b){ this.b = b; } public void run(){ b.run(); } }

Men jag vill kunna använda denna klass A för klasserna C och D som också har en metod som heter run().

Är detta ett utmärkt tillfälle att använda Java Generics då? Ifall JA: Hur ska jag göra?

Om klasserna C och D ärver (extends) klass B kan du låta konstruktorn ta typ B och inte tänka mer på saken. I detta scenario är ett objekt av klass C eller D även ett objekt av klass B — arvet säkerställer att B, C och D har en run()-metod.

Av Teknocide
Skrivet av heretic16:

Så hur ska jag göra för att kombinera vissa metoder och parametrar från Vehicle och Person i klassen Robot?

Du kan skapa en mellanliggande abstrakt datatyp (klass) som innehåller mer information. Exempel

abstract class A { public int foo = 1; } abstract class B extends A { public int bar = 2; } class C extends B { public C(foo, bar) { this.foo = foo; this.bar = bar; } }

För många arv gör din design väldigt stel och jobbig att arbeta med. Det blir liksom alltid hårklyverier: Kan alla människor verkligen prata? Hur är det med stumma människor? Bebisar? Tystnadslöfte? Stoppar vi in en ny klass i mitten av arvskedjan som heter Being och representerar något som inte nödvändigtvis kan prata så blir det en massa omstrukturering bland klasserna för att flytta metoder till den nya klassen osv.

Java har som sagt inte stöd för multipla arv — men en klass kan implementera flera "interfaces". Sedan Java 8 har interfaces fått stöd för default methods vilka tillåter arv av metoder, med den begränsningen att de metoderna inte kan påverka en instans tillstånd (state).

Av Teknocide

@MaxieTheHatter
Java 10 har släppts och 9 är redan EOL. I september kommer Java 11.