Działanie Calendar.getInstance();

0

Hej,

Jak mam rozumimeć ten kod:

Calendar C1 = Calendar.getInstance();

Rozumiem, że jest to wywołanie statycznej metody, klasy Calendar ale już w ten sam sposób nie mogę wywołać dla innej klasy jakiejś metody statycznej, np coś takiego:

public class Obiekty 
{
    public static void odtwarzacz2(String t)
    {
        System.out.println(t);
    }
}
public class Testy 
{
 
    public static void main(String[] args) 
    {
Obiekty O2 = Obiekty.odtwarzacz2("test2");
    }

W takim przypadku nie mogę wywołać mojej statycznee metody odtwarzacz2. Co źle zrozumiałem?

0

Do końca nie opisałeś błędu kompilacji itd, ale z tego co mi się w oczy rzuca w pierwszej kolejce -> odtwarzacz2 zwraca void zamiast instancję klasy Obiekty, zaimplementuj public static Obiekty odtwarzacz2(String t)

0
robertwadowski napisał(a):

Do końca nie opisałeś błędu kompilacji itd, ale z tego co mi się w oczy rzuca w pierwszej kolejce -> odtwarzacz2 zwraca void zamiast instancję klasy Obiekty, zaimplementuj public static Obiekty odtwarzacz2(String t)

Ogólnie to nie rozumiem jak to się dzieje, że używając tego kodu

Calendar C1 = Calendar.getInstance();

mogę w dalszej kolejności używac metod klasy Calendar, które są niestatyczne, używając zmiennej C1. Jak to się dzieje?

0

Generalnie dzieje się to tak, że metoda statyczna nie potrzebuje instancji klasy. tj taka metoda "fabryka" która tworzy Ci taką instancję np

public class A {

       public static A create() {
           return new A();
       }

       public void print() {
         System.out.println("print of A");
      }
}

W tym przykładzie:

  1. metoda create() ma za zadanie stworzyć instancję klasy A, ale ze względu na to, że jest static nie musi być wyowałana na rzecz jakiejś instancji
  2. metoda print() ma za zadanie printować jakiś tekst, musi być wywołana na rzecz konkretnej instancji obiektu
2

Widzę, że temat z przed 2 dni, ale nie jestem pewien czy kolega zrozumiał. Kod dla klasy Calendar wygląda prawdopodobnie tak:

public class Calendar
{
	protected Calendar() { }

	public static Calendar getInstance()
	{
		return new Calendar();
	}
}

Jak widzisz konstruktor tej klasy jest protected więc nie możesz stworzyć jej nowej instancji tą drogą (chyba, że wewnątrz tej klasy):

Calendar kalendarz = new Calendar();

Działania new przypisane są do konstruktorów, spójrz

public class Car
{
	protected Car() { }
	protected Car(int liczba) { }
	protected Car(string wyraz) { }
	public Car(string wyraz, string drugiWyraz) { }
}

Car samochod = new Car() //ERROR
Car samochod = new Car(10) //ERROR
Car smaochod = new Car("cokolwiek") //ERROR
Car samochod = new Car("cokolwiek", "cokolwiek") //OK! bo tylko ten konstruktor jest publiczny

Konstruktor nie robi nic więcej jak zwraca nową instancję z tym co jej przypiszesz wewnątrz niego.
Generalnie tworzenie instancji obiektu przez new jest przez wielu uważane za antywzorzec. Jakie to ma zastosowanie? np.

public class Car
{
	public string Mark { get; protected set; }

	protected Car(string mark)
	{
		Mark = mark;
	}

	public static Car CreateFerrari()
	{
		return new Car("Ferrari");
	}

	public static Car CreateMercedes()
	{
		return new Car("Mercedes");
	}

	public static Car CreateBMW()
	{
		return new Car("BMW");
	}
}

Piszesz klasę takiego samochodu i nie chcesz dać jej użytkownikowi możliwości tworzenia samochodu marki 'samochód', no bo co to niby jest? W przyrodzie takie nie występują i lepiej żeby w twoim kodzie też nie wystepowały. Teraz ma możliwość stworzenia go (w aktualnej wersji) na trzy sposoby.

	Car samochod = Car.CreateFerrari();
	Car samochod = Car.CreateMercedes();
	Car samochod = Car.CreateBMW();

Marka jest odgórnie przypisana do każdego - i o to chodzi! ^^

Pozdrawiam
Wesołych Świąt

0

@dzziwny: Dziękuję za wyjaśnienie, dużo mi to porządkuje.
Mam jeszcze pytanie do takiego wywołania (to chyba podobna sytuacja):

		Sequencer sekwenser = MidiSystem.getSequencer();
		sekwenser.open();

W pierwszej linijce wywołuję statyczną metodę getSequencer() o typie Sequencer?
Ta metoda (jak w Twoim przykładzie wyżej) pozwala mi prawdopodobnie na utworzenie obiektu klasy Sequencer (tam też pewnie konstruktor jest protected)?

Jeżeli dobrze zrozumiałem powyższe to rozumiem za bardzo czemu w klasie MidiSystem mam metodę służącą do stworzenia obiektu klasy Sequencer?

Nie powinno to wyglądać tak?:
Sequencer sekwenser = Sequencer.getSequencer();
0

Zasadnicze pytanie: czy MidiSystem który podałeś, to nazwa klasy, czy już jej instancja?

Rozwiązań na twoje pytanie w sumie jest kilka...

  1. Klasa MidiSystem zawiera pole Sequencer, a metoda getSequencer zwraca to pole. W zalezności czy to klasa, czy instancja, to pole to jest statyczne, lub nie.
  2. MidiSystem dziedziczy po Sequencer i faktycznie może tworzyć tu instancję MidiSystem, albo Sequencer.
  3. Metoda getSequencer jest rozszerzeniem do klasy MidiSystem i w jakiś sposób tworzy nową instancję klasy sequencer z instancji midisystem.

Tak czy owak, normalnym jest, że metody jednych klas zwracają typy innych. Nie ważne czy to są konstruktory czy nie.

A co myślisz o takim przykładzie? ^^

string sekwenser = MidiSystem.ToString();

Jak go rozumiesz (a pewnie rozumiesz) to przelóż sobie to na swój kod analogicznie.

Jeśli dalej nie wymyślisz, to:

public static class MidiSystem
{
	private static Sequencer _sequencer;

	public static Sequencer getSequencer()
		=> _sequencer
}

Pozdrawiam, wszystkiego dobrego w nowym roku ^^

0

Tak mi się przypomniało, odnośnie początkowego pytania w pierwszym poście na temat:

Calendar C1 = Calendar.getInstance();

klasa Calendar prawdopodobnie jest singletonem, czyli jej instancja jest tworzona tylko raz i potem zwracana wielokrotnie i wszystko to się dzieje w metodzie getInstance(). Coś takiego:

public class Calendar
{
	// public string cokolwiek;
	// public int cokolwiek2;
		
	private static Calendar _calendar; // pole takiego samego typu co sama klasa

	private Calendar(); // prywatny konstruktor, więc nie można użyć 'new Calendar()' poza klasą

	public static getInstance() // zawsze zwraca jadną, tę samą instancję klasy - '_calendar'. jak jeszcze jej nie ma no to tworzy
	{
		if (_calendar == null)
		{
			_calendar = new Calendar();
		}

		return _calendar;
	}
}

Dodam tylko, że osobiście nie polecam tworzyć singletonów tą drogą, o wiele zdrowsze do takiej zabawy są kontenery IoC. temat jest z javy, więc niestety nie polecę żadnego konkretnego frameworka.

1

@dzziwny, nie zgadłeś.

    public static Calendar getInstance()
    {
        Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
        cal.sharedZone = true;
        return cal;
    }

    private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        Calendar cal = null;

        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype == null) {
            // Calendar type is not specified.
            // If the specified locale is a Thai locale,
            // returns a BuddhistCalendar instance.
            if ("th".equals(aLocale.getLanguage())
                    && ("TH".equals(aLocale.getCountry()))) {
                cal = new BuddhistCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        } else if (caltype.equals("japanese")) {
            cal = new JapaneseImperialCalendar(zone, aLocale);
        } else if (caltype.equals("buddhist")) {
            cal = new BuddhistCalendar(zone, aLocale);
        } else {
            // Unsupported calendar type.
            // Use Gregorian calendar as a fallback.
            cal = new GregorianCalendar(zone, aLocale);
        }

        return cal;
    } 
1

Klasa Calendar jest tak głupia (konfudująca), że nie powinno się jej używać.
Od razu warto zmienić na LocalDateTime (.now() ).

1 użytkowników online, w tym zalogowanych: 0, gości: 1