Tak jak w temacie mam dość błahy problem, mianowicie stworzyłem obiekt klasy A w klasie B i potrzebuje go przekopiować lub dostać się do składowych w klasie C.
Każda próba kończy się nullpointerem.
Mógłby ktoś podesłać parę linijek jak by to wyglądało z 1 zmienna.
A czemu nie możesz obiektu A stworzyć w jakimś miejscu poza klasami B i C i go do nich wstrzyknąć ?
Generalnie chodziło mi o coś takiego, liczyłem że mam jakiś zawias ale w tym przykładzie bangla. Coś więcej o wstrzykiwaniu ?
public class Main {
public static void main(String[] args) {
UserModel userModel= new UserModel();
//userModel.addName();
userModel.user.setName("Jacek");
User user;
System.out.println(userModel.user.getName());
System.out.println(userModel.getUser().getName());
}
}
public class User {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class UserModel {
User user = new User();
public void addName(){
user.setName("Jan");
}
public User getUser(){
return user;
}
}
Chyba tak to będzie:
class B {
private A a;
A getA() {
return a;
}
}
class C {
private A a = null;
void setA(A a) {
this.a = a;
}
}
wywołanie :
A a = new A();
C c = new C();
c.setA(a.getA());
Zadziała jesli wszystkie klasy będą w tym samym pakiecie, jeśli nie to ustaw modyfikatory widoczności na public.
Pisany napisał(a):
Generalnie chodziło mi o coś takiego, liczyłem że mam jakiś zawias ale w tym przykładzie bangla. Coś więcej o wstrzykiwaniu ?
public class Main { public static void main(String[] args) { UserModel userModel= new UserModel(); //userModel.addName(); userModel.user.setName("Jacek"); User user; System.out.println(userModel.user.getName()); System.out.println(userModel.getUser().getName()); } }
public class User { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class UserModel { User user = new User(); public void addName(){ user.setName("Jan"); } public User getUser(){ return user; } }
Tworzysz obiekt A poza klasami i dodajesz go do konstruktora jako parametr, czyli wstrzykujesz obiekt do środka
np.
A a = new A();
B b = new B(a);
C c = new C(a);
a w srodku klasy:
class B {
private A a;
B(A a) {
this.a = a;
}
}
Tak samo w klasie C i masz ten sam obiekt w dwóch klasach.
Coś jest nie tak otrzymuje 2 różne adresy obiektu.
Zmieńmy przykład może, mam klasy:
Player - zawiera składowe +gettery/settery
PlayerModel - deklaruje i tworze nowy obiekt Player +getPlayer
Controller - deklaruje playerModel i sout(playerModel.getPlayer)
Pisany napisał(a):
Generalnie chodziło mi o coś takiego, liczyłem że mam jakiś zawias ale w tym przykładzie bangla. Coś więcej o wstrzykiwaniu ?
public class Main { public static void main(String[] args) { UserModel userModel= new UserModel(); //userModel.addName(); userModel.user.setName("Jacek"); User user; System.out.println(userModel.user.getName()); System.out.println(userModel.getUser().getName()); } }
public class User { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class UserModel { User user = new User(); public void addName(){ user.setName("Jan"); } public User getUser(){ return user; } }
Jak ma działać wg Ciebie linia w mainie: userModel.user.setName("Jacek");
?
Przecież pole User user = new User();
jest domyślnie prywatny więc nie możesz się z maina odwołać bezpośrednio do tego pola.
Jak już to w mainie powinno być userModel.getUser().setName("Jacek");
.
wyebani napisał(a):
Jak ma działać wg Ciebie linia w mainie:
userModel.user.setName("Jacek");
?
Przecież poleUser user = new User();
jest domyślnie prywatny więc nie możesz się z maina odwołać bezpośrednio do tego pola.Jak już to w mainie powinno być
userModel.getUser().setName("Jacek");
.
Oby dwa wypisują Jacek sprawdzone, inaczej tego bym nie wrzucał.
Jeszcze raz, tym razem wstawię kod o który mi chodzi. Chciałbym w tej klasie:
public class TopMenuIconsController implements Initializable {
public ImageView avatarTopMenuIcons;
public Label levelTopMenuIcons;
public Label cashTopMenuIcons;
public Label cashInBankTopMenuIcons;
public Label nameTopMenuIcons;
public Player player;
@Override
public void initialize(URL location, ResourceBundle resources) {
PlayerModel playerModel=new PlayerModel();
System.out.println(playerModel.getPlayer());
System.out.println(player);
// nameTopMenuIcons.setText(player.getName());
// levelTopMenuIcons.setText(Integer.toString(player.getLevel()));
// cashTopMenuIcons.setText("100");
// cashInBankTopMenuIcons.setText("2000");
// Image image = new Image(String.valueOf(player.getAvatar()));
// avatarTopMenuIcons.setImage(image);
}
}
żeby za // linie działały, żeby któryś ze sout zwracał mi taka samą referencje jak System.out.println(player); w klasie PlayerModel.
Player jest stworzony w tej klasie
public class PlayerModel {
public Player player = new Player();
public void createPlayer(int id, String name) {
PlayerDao playerDao = new PlayerDao(DbManager.getConnectionSource());
player.setId(id);
player.setName(name);
player.setLevel(1);
player.setStrange(8);
player.setAgility(8);
player.setCharisma(8);
player.setIntellect(8);
playerDao.createOrUpdate(player);
playerDao.refresh(player);
DbManager.closeConnectionSource();
System.out.println("Player w PlayerModel.createPlayer:");
System.out.println(player);
}
public Player getPlayer(){
return player;
}
}
Nie rozumiem, porównując do Main, User, UserModel to jest to samo.
@Pisany: jeżeli chodzi o ostatni przykład, dlaczego zakomentowałeś kod? Nie pojawia się przypadkiem NullPointerException w pierwszej zakomentowanej linii? W tym przypadku problemem jest to że player nie jest nigdy inicjalizowany, a dlaczego? Bo jest to inny player, niż ten który tworzysz przy okazji tworzenia instancji typu PlayerModel. Obiekty tego samego typu, ale inne wartości.
Ale wracając do sedna, chciałbyś operować w dwóch klasach na tym samym obiekcie. Przykład podany przez @vakil jest poprawny
vakil napisał(a):
Tworzysz obiekt A poza klasami i dodajesz go do konstruktora jako parametr, czyli wstrzykujesz obiekt do środka
np.
A a = new A(); B b = new B(a); C c = new C(a);
a w srodku klasy:
class B { private A a; B(A a) { this.a = a; } }
Tak samo w klasie C i masz ten sam obiekt w dwóch klasach.
To jest jedno z podejść, spróbuj na takich prostych klasach może najpierw aby to zrozumieć. W tym przypadku jest tworzony obiekt A (nazwijmy go objectA), a następnie przekazywana referencja (adres tego obiektu) do obiektów typu B i C w konstruktorze. Jeżeli teraz implementacja klasy B albo C będzie operować na objectA, to będzie on zmodyfikowany w obu obiektach.
Dobra, a teraz wyeliminujmy w końcu ten błąd który masz w pierwszej zakomentowanej linii. Jak pisałem pole player w klasie TopMenuIconsController jest nullem. Chciałbyś teraz do niego przypisać obiekt stworzony w PlayerModel, więc musisz go przypisać.
player = playerModel.getPlayer();
takim o to cudem możesz odkomentować pierwszą linię, z kolejnymi bym się wstrzymał bo znowu natrafisz na NPE.
Ja w klasie Player stworzylbym wewnętrzna klasę PlayerBuilder (skoro autor potrzebuje buildera) i w ten sposób tworzył obiekt, bez jakiejś dziwnej klasy PlayerModel, która w zasadzie nic nie robi.
vakil napisał(a):
Tworzysz obiekt A poza klasami i dodajesz go do konstruktora jako parametr, czyli wstrzykujesz obiekt do środka
np.
A a = new A(); B b = new B(a); C c = new C(a);
a w srodku klasy:
class B { private A a; B(A a) { this.a = a; } }
Tak samo w klasie C i masz ten sam obiekt w dwóch klasach.
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class UserModel {
private User user;
public UserModel(User user){
this.user= user;
}
}
public class Main {
public static void main(String[] args) {
User user= new User();
user.setName("JAN");
System.out.println(user.getName());
UserModel userModel=new UserModel(user);
System.out.println("user: "+user);
System.out.println("userModel: "+userModel);
}
}
JAN
user: User@48140564
userModel: UserModel@58ceff1
vakil napisał(a):
Chyba tak to będzie:
class B { private A a; A getA() { return a; } } class C { private A a = null; void setA(A a) { this.a = a; } }
wywołanie :
A a = new A(); C c = new C(); c.setA(a.getA());
Zadziała jesli wszystkie klasy będą w tym samym pakiecie, jeśli nie to ustaw modyfikatory widoczności na public.
public class User {
User(String name){
this.name=name;
}
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class UserModel {
User user=new User("Jan");
User getUser(){
return user;
}
}
public class Top {
User user=null;
void setUser(User user){
this.user=user;
}
User getUser(){
return user;
}
void writeTopUser(){
System.out.println(user);
}
}
public class Main {
public static void main(String[] args) {
UserModel userModel= new UserModel();
Top top = new Top();
System.out.println("User z userModel");
System.out.println(userModel.getUser());
System.out.println(userModel.getUser().getName()+"\n");
System.out.println("User z TOP przed ");
System.out.println(top.getUser()+"\n");
System.out.println("User z TOP po");
top.setUser(userModel.getUser());
System.out.println(top.getUser());
}
}
User z userModel
User@75412c2f
Jan
User z TOP przed
null
User z TOP po
User@75412c2f
Czyli działa tak jak bym chciał ^ ^
Reasumując nie ważne w jakiej klasie stworze obiekt "a" ale musi tam być getter do "a" , a nie w klasie A. Tak ?
EDIT
Nie działa w głównym
public class PlayerModel {
public Player player= new Player();
public void createPlayer(int id, String name) {...}
public Player getPlayer() {
return player;
}
}
public class TopMenuIconsController implements Initializable {
public ImageView avatarTopMenuIcons;
public Label levelTopMenuIcons;
public Label cashTopMenuIcons;
public Label cashInBankTopMenuIcons;
public Label nameTopMenuIcons;
Player player=null;
PlayerModel playerModel = new PlayerModel();
@Override
public void initialize(URL location, ResourceBundle resources) {
setPlayer(playerModel.getPlayer());
System.out.println("Player w topMenu");
System.out.println(player);
// nameTopMenuIcons.setText(player.getName());
// levelTopMenuIcons.setText(Integer.toString(player.getLevel()));
// cashTopMenuIcons.setText("100");
// cashInBankTopMenuIcons.setText("2000");
// Image image = new Image(String.valueOf(player.getAvatar()));
// avatarTopMenuIcons.setImage(image);
}
public void setPlayer(Player player) {
this.player = player;
}
}
Zdaje się że zrobiłem wszystko tak samo poza jednym. wywołałem setPlayer(playerModel.getPlayer()); bez utworzenia nowego obiektu TopMenuIconsControlle, po utworzeniu dostaje masę błędów z initialize.
Dobra, mam to na konstruktorach. Dzięki wielkie wszystkim, za pomoc jak i krytykę. :)