Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Metody statyczne


Mickey2

Rekomendowane odpowiedzi

Opublikowano

Witam, wytlumaczy mi ktos dlaczego nie mozna robic metod statycznie, wplywa to na optymalnosc kodu czy jak. I np mam kod na sidebar i chce dodac cos do tego sidebara z innej klasy jak to zrobic niestatycznie, bo statycznie to wiem.

Opublikowano
11 minut temu, ZiomeczekTVGC napisał:

Kto ci napisał, że nie wolno używać metod/pól statycznych? Normalnie możesz sobie w osobnej klasie dać metodę statyczną i używać jej z innych klas.

chodzi mu o to, czy jak nie bedzie robil statycznie to czy kod bedzie tak jakby "wydajniejszy/optymalniejszy"

 

osobiście byłem na discordzie i mi też pisali czemu robie prawie wszystko statycznie.

@topic

w sumie to dołączam sie do pytania.

 

Aktualnie interesuję się javą, powoli ogarniam java swing i awt, czasem bawię się HTML.

Opublikowano

Potrzebuję odczytać sidebar w inne klasie. Zrobiłem sobie coś takiego. Do sidebara mam api.

public static SideBar sb = new SideBar("TEST");

public static SideBar getSb();

 return sb;

To jest statycznie, i odczytuje je sobie w innej klasie, czy tak jest optymalnie?

Opublikowano
41 minut temu, Mickey2 napisał:

Potrzebuję odczytać sidebar w inne klasie. Zrobiłem sobie coś takiego. Do sidebara mam api.

public static SideBar sb = new SideBar("TEST");

public static SideBar getSb();

 return sb;

To jest statycznie, i odczytuje je sobie w innej klasie, czy tak jest optymalnie?

caly czas tworzysz nowy sidebar, jak chcesz bawic sie w sidebara to mozesz uzyc tego:

package net.yooniks.sidebar;

import com.keenant.sidebar.Sidebar;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class SidebarPlugin extends JavaPlugin{

    private SidebarPlugin plugin;

    private Map<UUID, Sidebar> sidebarMap = new HashMap<>();

    public SidebarPlugin(){
        plugin = this;
    }

    @Override
    public void onEnable() {

        if (this.getServer().getPluginManager().getPlugin("PlaceholderAPI") == null){
            this.getLogger().info("Could not find PlaceholderAPI! Plugin can not work wihout it! Download placeholderapi here: https://www.spigotmc.org/resources/placeholderapi.6245/");
            this.getServer().shutdown();
            return;
        }

        this.saveDefaultConfig();

        new ConfigManager(this);
        ConfigManager.load();
        this.getServer().getPluginManager().registerEvents(new Listener() {
            @EventHandler
            public void onJoin(PlayerJoinEvent e) {
                initSidebar(e.getPlayer());
            }
        }, this);
        this.getServer().getScheduler().runTaskTimerAsynchronously(this, new Runnable() {
            @Override
            public void run() {
                for (Player player : getServer().getOnlinePlayers())

                    getServer().getScheduler().runTask(plugin, () -> {
                        initSidebar(player);
                    });
            }
        }, ConfigManager.delay*20, ConfigManager.delay*20);
    }

    private void initSidebar(Player player) {
        final UUID uuid = player.getUniqueId();
        if (!this.sidebarMap.containsKey(uuid)){
            List<String> list = ConfigManager.list;
            int i = list.size();
            final Sidebar sidebar = new Sidebar("y-Sidebar");
            player.setScoreboard(sidebar.getScoreboard());
            sidebar.setTitle(fixColor(ConfigManager.header));
            for (String string : list) {
                string = PlaceholderAPI.setPlaceholders(player, string);
                sidebar.set(i, fixColor(string));
                i--;
            }
            this.sidebarMap.put(uuid, sidebar);
        }
        else{
            List<String> list = ConfigManager.list;
            int i = list.size();
            final Sidebar sidebar = this.sidebarMap.get(uuid);
            player.setScoreboard(sidebar.getScoreboard());
            for (String string : list) {
                string = PlaceholderAPI.setPlaceholders(player, string);
                sidebar.replace(i, fixColor(string));
                i--;
            }
        }

    }

    public int getPing(Player p) {
        try {
            String serverName  = Bukkit.getServer().getClass().getPackage().getName(),
                    serverVersion = serverName.substring(serverName.lastIndexOf(".") + 1, serverName.length());
            Class<?> CPClass;
            CPClass = Class.forName("org.bukkit.craftbukkit." + serverVersion + ".entity.CraftPlayer");
            Object CraftPlayer = CPClass.cast(p);

            Method getHandle = CraftPlayer.getClass().getMethod("getHandle", new Class[0]);
            Object EntityPlayer = getHandle.invoke(CraftPlayer, new Object[0]);

            Field ping = EntityPlayer.getClass().getDeclaredField("ping");

            return ping.getInt(EntityPlayer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    private int getPlayersOnline(){
        int playersOnline = 0;
        try {
            if (Bukkit.class.getMethod("getOnlinePlayers", new Class<?>[0]).getReturnType() == Collection.class)
                playersOnline = ((Collection<?>)Bukkit.class.getMethod("getOnlinePlayers", new Class<?>[0]).invoke(null, new Object[0])).size();
            else
                playersOnline = ((Player[])Bukkit.class.getMethod("getOnlinePlayers", new Class<?>[0]).invoke(null, new Object[0])).length;
        }
        catch (NoSuchMethodException ex){} 
        catch (InvocationTargetException ex){}
        catch (IllegalAccessException ex){} 
        return playersOnline;
    }


    private String fixColor(String text) {
        return ChatColor.translateAlternateColorCodes('&', text.replace(">>", "»").replace("<<", "«").replace("*", "•"));
    }

}
package com.keenant.sidebar;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import lombok.Data;
import lombok.Getter;
import lombok.ToString;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;

@ToString
public class Sidebar {
    @Getter private final Scoreboard scoreboard;
    @Getter private final Multimap<Integer,SpecialTeam> teams;
    @Getter private final Objective objective;

    /**
     * Creates a new sidebar with a new scoreboard attachment.
     */
    public Sidebar() {
        this(Bukkit.getScoreboardManager().getNewScoreboard());
    }

    /**
     * Creates a new titled sidebar with a new scoreboard attachment.
     * @param title
     */
    public Sidebar(String title) {
        this(Bukkit.getScoreboardManager().getNewScoreboard(), title);
    }

    /**
     * Creates a new sidebar with the given scoreboard.
     */
    public Sidebar(Scoreboard scoreboard) {
        this(scoreboard, UUID.randomUUID().toString().substring(0, 6));
    }

    /**
     * Creates a new titles sidebar with the given scoreboard.
     * @param title
     */
    public Sidebar(Scoreboard scoreboard, String title) {
        Preconditions.checkNotNull(scoreboard, "Sidebar scoreboard must not be null");
        Preconditions.checkNotNull(title, "Sidebar title must not be null");

        this.scoreboard = scoreboard;
        this.teams = ArrayListMultimap.create();

        this.objective = scoreboard.registerNewObjective(title, "dummy");
        this.objective.setDisplayName(title);
        this.objective.setDisplaySlot(DisplaySlot.SIDEBAR);
    }

    /**
     * Retrieve the title of the sidebar.
     * @return
     */
    public String getTitle() {
        return this.objective.getDisplayName();
    }

    /**
     * Changes the title of the sidebar.
     * @param text
     */
    public void setTitle(String text) {
        this.objective.setDisplayName(text);
    }

    /**
     * Adds a line to the sidebar at the given line (score) number.
     * @param line
     * @param text
     */
    public void set(int line, String text) {
        text = fixDuplicates(text);
        SpecialTeam specialTeam = createSpecialTeam(text, line);
        Team team = specialTeam.getTeam();
        team.addEntry(specialTeam.getLineText());
        this.objective.getScore(specialTeam.getLineText()).setScore(line);
        this.teams.put(line, specialTeam);
    }

    /**
     * Get all text at the given line (score) number.
     * @param line
     * @return
     */
    public List<String> get(int line) {
        List<String> lines = new ArrayList<>();
        for (SpecialTeam team : this.teams.get(line))
            lines.add(team.getFullText());
        return lines;
    }

    /**
     * Get the line (score) number of the given text.
     * @param text
     * @throws IllegalArgumentException If the text cannot be found in the sidebar.
     * @return
     */
    public int getLine(String text) throws IllegalArgumentException {
        for (Entry<Integer, SpecialTeam> entry : this.teams.entries())
            if (entry.getValue().getFullText().equals(text))
                return entry.getKey();
        throw new IllegalArgumentException("line not found");
    }

    /**
     * Removes all entries with the given line (score) number and sets new text.
     * @param line
     * @param text
     */
    public void replace(int line, String text) {
        remove(line);
        set(line, text);
    }

    /**
     * Removes all entries with the given text.
     * @param text
     */
    public void remove(String text) {
        remove(text, null);
    }

    /**
     * Removes all entries with the given line (score) number.
     * @param line
     */
    public void remove(int line) {
        remove(null, line);
    }

    /**
     * Removes all entries in the sidebar.
     */
    public void removeAll() {
        remove(null, null);
    }

    /**
     * Removes all entries with the given text and line (score) number.
     * @param text
     */
    public void remove(String text, Integer line) {
        Iterator<Entry<Integer, SpecialTeam>> iterator = this.teams.entries().iterator();
        while (iterator.hasNext()) {
            Entry<Integer, SpecialTeam> entry = iterator.next();
            if (text != null && !entry.getValue().getFullText().equals(text))
                continue;
            if (line != null && !entry.getKey().equals(line))
                continue;
            this.scoreboard.resetScores(entry.getValue().getLineText());
            entry.getValue().getTeam().unregister();
            iterator.remove();
        }
    }

    private String fixDuplicates(String text) {
        boolean unique = false;
        while (!unique) {
            unique = true;
            for (SpecialTeam team : this.teams.values()) {
                if (team.getFullText().equals(text)) {
                    text += ChatColor.RESET;
                    unique = false;
                }
            }
        }
        return text;
    }

    private SpecialTeam createSpecialTeam(String text, int lineNum) {
        String[] split = getSplitText(text);

        String prefix = split[0];
        String line = split[1];
        String suffix = split[2];

        Team team = this.scoreboard.registerNewTeam("sb-" + lineNum + "-" + UUID.randomUUID().toString().substring(0, 6));

        if (prefix != null)
            team.setPrefix(prefix);

        if (suffix != null)
            team.setSuffix(suffix);

        return new SpecialTeam(team, line, text);
    }

    private String[] getSplitText(String text) {
        Splitter splitter = Splitter.fixedLength(16);
        List<String> split = Lists.newArrayList(splitter.split(text).iterator());

        String prefix = null;
        String line = split.get(0);
        String suffix = null;

        if (text.length() > 16) {
            prefix = split.get(0);
            line = split.get(1);
        }
        if (text.length() > 32)
            suffix = split.get(2);

        return new String[] {prefix, line, suffix};
    }

    @ToString
    @Data
    private class SpecialTeam{
        private Team team;
        private String lineText;
        private String fullText;
        
		public String getFullText() {
			return fullText;
		}
		
		public String getLineText(){
			return lineText;
		}
		
		public Team getTeam(){
			return team;
		}
		
		public SpecialTeam(Team team, String line, String text){
			this.team = team;
			this.lineText = line;
			this.fullText = text;
		}
        
        
    }

	public Scoreboard getScoreboard() {
		return scoreboard;
	}
}

 

sidebar robiony ok. miesiąc temu, ale dalej działa.

44 minuty temu, Mickey2 napisał:

Potrzebuję odczytać sidebar w inne klasie. Zrobiłem sobie coś takiego. Do sidebara mam api.

public static SideBar sb = new SideBar("TEST");

public static SideBar getSb();

 return sb;

To jest statycznie, i odczytuje je sobie w innej klasie, czy tak jest optymalnie?

Cytat

public static SideBar sb = new SideBar("TEST");

public static SideBar getSb();

 return sb;

ohoho, jak ty tak bawisz sie z kodem to na pewno bedzie nieoptymalne

nieoptymalne bo zrobiles sobie jeden field statyczny, i jedną metode? wuuut

 

Aktualnie interesuję się javą, powoli ogarniam java swing i awt, czasem bawię się HTML.

Opublikowano

głownie chodzi o to że jak robisz metode statyczną to nie jest ona robiona w kontekscie żadnego obiektu tzn jak zrobisz

public class Obiekt {

 public int a;

 public int b;

 public static String abc;

}

i jak zrobisz nową instacje obiektu tzn
Obiekt obiekt = new Obiekt(); to w niej bedziesz mial obiekt.a i obiekt.b czyli dla każdego obiektu a,b beda dynamicznie zmieniane a abc będzie "statyczne" dla całego projektu i nie dostaniesz się do niej za pomocą
instacje obiektu ale Obiekt.abc;

przykład:

public class User{

 

public static List<User> users = new ArrayList<>();

 

public String nick,uuid;

}

i teraz dla każdego usera zminne nick,uuid bedą dynamiczne ale dla całego projektu będzię tylko jedna lista users i do niej byś sie dostawał User.users.add(user); 

Nie wiem czy dobrze to wytłumaczyłem, pewnie też mało profesjonalnie ale powinieneś zrozumieć, co do optymalność, to nawet jej nie zauważysz robiąc pluginy pod bukkita xD

Opublikowano

jak nie chcesz robic sobie czegos statycznie to mozesz pobawic sie tak:

public class MyFirstBukkitPlugin {

	private MyOtherClass sidebar;
	
	@Override
	public void onEnable(){
		this.sidebar = new MyOtherClass(this);
	}

	public MyOtherClass getSidebar(){
		return this.sidebar;
	}
}

###################
public class MyOtherClass{

	private JavaPlugin plugin;
	
	public MyOtherClass(JavaPlugin plugin){
		this.plugin = plugin;
	}
		
	void method(){
		plugin.getSidebar().nextMethod(); //niestatycznie
	}
}

 

 

Aktualnie interesuję się javą, powoli ogarniam java swing i awt, czasem bawię się HTML.

Opublikowano

co do tego czy jest wydajniejsze to praktycznie nie ma różnicy między polem statycznym a normalnym . w każdym przypadku odnosi się do jakiegoś indeksu w pamięci (32/64) ..

java jest jezykiem "wysokiego poziomu" , jest strikte obiektowa , dynamiczna. dlatego raczej się nie stosuje statyków , co nie oznacza że sa jakieś gorsze dlatego należy je omijać. najprościej można to porównać do smażenia jajek w garnku , da sie i niczym by się nie różniły od smażonych na patelni, ale jak nie ma potrzeby to się tego nie robi, bo i po co.

 

Opublikowano

Spróbuję jakoś na chłopski rozum Wam wytłumaczyć, ale niech przyjdzie @GotoFinali poda jakieś dane które wykopał z zamętów JRE gdy miał siedem lat, bo na pewno takimi dysponuje, plus pomiary do tego.

 

Pierwszą rzeczą na którą należy zwrócić uwagę jest to, ile będzie obiektów klas w których są statyczne pola czy metody. Jeśli stworzymy taki obiekt SideBar i mamy jeden taki na cały plugin, a pole jest w głównej klasie pluginu, to czemu nie? To pole może być statyczne, jeśli nie chcemy bawić się w pobieranie instancji tego pluginu. Jeśli natomiast każdy gracz ma swój SideBar, a Collection/Set/Map z tymi SideBarami przechowujemy w klasie na przykład gildii, teamu, czegokolwiek innego, to wtedy pole nie może być statyczne, bo będzie współdzielone pomiędzy każdym obiektem tej klasy.

public MyPlugin getInstance() {

    return instance;

}

 

Nie tworzymy (publicznych) statycznych pól i metod jeśli nie chcemy żeby ktoś miał do nich dostęp. Jak ktoś będzie chciał to i tak ten dostęp zdobędzie, ale przynajmniej będzie wiedział, że nie powinien.

public static Object getAllPasswords();

public static void executeSomeSuperUnsafeCodeAndCrash();

 

Tworzymy statyczne pola jeśli wartości są stałe.

public static int TPS = 20;

 

Metody są statyczne kiedy nie potrzebują żadnych danych innych niż te, które przekazane są w argumentach (to w dużym uproszczeniu) Do tego zaliczają się wszelakie utilsy.

ChatColor.translateAlternateColorCodes

public static boolean isALarger(int a, int b ) {

    return a > b;

}

Dodaj mój nick do posta jeśli potrzebujesz pomocy | Piszę pluginy na zlecenie | Pomagam z Linuxem

newlogo.png

Opublikowano
Dnia 8.09.2017 o 12:20, Mickey2 napisał:

Witam, wytlumaczy mi ktos dlaczego nie mozna robic metod statycznie, wplywa to na optymalnosc kodu czy jak. I np mam kod na sidebar i chce dodac cos do tego sidebara z innej klasy jak to zrobic niestatycznie, bo statycznie to wiem.

Ogólnie statycznych metod się jako-tako unika bo java to język obiektowy, no ale oczywiście takie 100% unikanie jest bez sensu, bo wyjdą tylko jakieś dziwne potworki, np tak jak już ctrl wspomniał o metodach utilsach.
Tylko trzeba tutaj potrafić rozróżnić zwykłe utilsy od logiki tego co tworzymy, np wysłanie wiadomości do wszystkich graczy o starcie areny w pluginie to nie koniecznie dobry materiał na statyczną metodę w utilsach, o czym jeszcze będzie niżej.

A dlaczego się unika? Dla łatwości zmian i zarządzania, wróćmy do areny, na początku każdy gracz dodaje wiadomość o jej starcie, możemy zrobić to na 3 sposoby: (od najgorszego do najlepszego)
- Tworzymy jakaś statyczną metodę jak sendStartMessage(Collection<? extends Player> players, String message) i po prostu używamy jej w metodzie gdzie startuje arena
- Tworzymy nie-statyczną metodę w klasie reprezentującą arenę, czyli taka metoda ma już dostęp do graczy, a wiadomość możemy jej podawać lub pobierać z innej metody czy też stałej.
- Tworzymy osobną klasę (najlepiej interfejs) np Announcer z metodą typu sendAnnouce(Player player) i klasa areny ma jedynie pole takiego typu i getter/setter, lub tylko getter i argument w konstruktorze czy też pochodzi z buildera. Arena tylko wywołuje go dla każdego z graczy przy starcie

No i teraz wyobraźmy sobie że nasz plugin się rozrasta, tworzy całą podstawową klasę areny która zarządza podstawowymi elementami, jak teleportowaniem graczy, wysyłaniem wiadomości, ustawianiem scoreboarda i 20042 innych rzeczy. Z czasem potrzebujemy tworzyć areny które nie są takie jak wszystkie, np musimy stworzyć arenę która wysyła wiadomość w którą da się kliknąć, lub ma jakieś dodatkowe specjalnie zmienne które trzeba zamienić osobno dla każdego gracza czy coś innego, i rozpatrzmy to pod kątem tych 3 rozwiązań:

Statyczna metoda: Musimy dla tej areny nadpisać całą metodę startującą arenę - zakładając że to w ogóle możliwe, może metoda odwołuje się do rzeczy package-local lub private do których nie mamy dostępu? Trzeba nagle przebudować cześć naszego pluginu tak by umożliwić tę jedną niby prostą zmianę, masa roboty której można było zapobiec wcześniej.

Metoda w klasie areny: Możemy łatwo nadpisać i zmienić, jednak dalej wymaga to rozszerzania klasy areny, co nie koniecznie może być czymś co chcemy robić. A do tego samo wysyłanie wiadomości nie jest jakoś związane z działaniem areny, to oznacza że skoro w taki sposób implementujemy wszystkie swoje featursy, to w klasie areny nagle jest kilkadziesiąt, czy kilkaset metod które robią coś niezwiązanego z samą areną - jeden welki burdel przez który trzeba scrollować.

Osobna klasa: zwyczajnie tworzymy inną implementacje Annoucera i podajemy ją do konstruktora areny - gotowe, nie musimy nawet rozszerzać klasy areny jeśli cały nasz system działa na takiej zasadzie, tylko podajemy różne moduły - gdzie każdy moduł wykonuje swoje zadanie.

 

Ale jesteś początkujący, więc... na początku jest się trudno przyzwyczaić do takiego pisania, często to trochę więcej pracy no i trzeba jednak zrozumieć sam koncept, jednak często zaoszczędza się znacznie więcej pracy potem. + trzeba to dobrze zrobić i przemyśleć.
Trochę odbiegam od tematu samych metod statycznych, ale jednak to się dość konkretnie ze sobą wiąże, ogólnie statycznych metod się unika i używa tylko do prostych operacji które działają tylko na otrzymanych danych, jak wszelakie proste utilsy, StringUtils z apache itd. Do reszty zawsze lepiej przygotować obiekt, możesz nawet domyślnie mieć gdzieś statyczną instance tego obiektu domyślnie używaną tam gdzie trzeba - tak długo jak da się ją prosto zmienić na inną w razie potrzeby.
Ale też jak ctrl pisał nie ma nic specjalnie złego w stworzeniu metody getInstance w pluginie - bo i tak nie ma możliwości by bylo ich więcej niż jeden, taki obiekt/klasę często nazywa się singletonem bo istnieje tylko jedna instancja.

1438614356923701010629.png

 

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...