Использование статических методов

Я пишу простой класс интерфейса, как показано ниже. Мне нужно сделать доступным пользователю только один из его методов. Пользователю, использующему этот класс, нужно только возвращаемое значение этого конкретного метода (checkLink). Поэтому я объявил только этот метод защищенным, чтобы он был виден только пользователю, вызывающему класс Iface. Поскольку остальные методы класса должны использоваться внутри класса, они были объявлены как частные. Я добавил ключевое слово Static, поскольку эти методы не имеют состояния. Я использовал ключевое слово static final для переменных класса, так как мне нужно было что-то вроде C, например #define.

Поскольку я программист на C, я все еще новичок в мире Java. Взгляните на скелет моего кода и скажите мне, верны ли сделанные заявления в передаче смысла.

package com.prog.Test;
import java.net.*;
import java.io.*;

public class Iface{   

    private static final int MSG_OK     =   0x01;
    private static final int MSG_NOK    =   0x00;   
    private static final int MSG_FAIL   =   0xFF;    

    private static byte[] getBytesFromUrl(URL link) throws IOException {
        ......                  
        return bytes;
    }               

    private static int[] msg_header(byte[] msg) throws Exception
    {
        int len = msg.length;
        System.out.println("len ="+len);
        int[] headerMsg =new int [3]; 
        headerMsg[0]= MSG_OK; 
            ......

        return headerMsg;
    }

    private static byte[] Tobyte(int[]src) {
            ....
    }

    protected static int checkLink (URL url ) throws IOException {

       byte[] rbuffer = null;
       byte[] hdr = null;
       int status = -1; 

        try{             
            rbuffer = getBytesFromUrl(url);
            ..
            ..
            hdr = Tobyte(msg_header(rbuffer));
            ...
            ...
            status = 0; 

        }catch (Exception e) {
            System.err.println("Exception:  " + e);
        }
        return status; 

  }
}

Поэтому, когда я использую этот класс Iface в приложении, я называю его так:

public class Trial {  

    public static void main (String [] args ) throws IOException {

        URL url = new URL("http://localhost:8000/myfile");

        System.out.println("Calling Iface");

        int retval = Iface.checkLink(url);      

        System.out.println("retval ="+retval);
    }
}

Я тоже пробовал это (после удаления ключевого слова static в методе checkLink()):

 public class Trial {  

        public static void main (String [] args ) throws IOException {

            URL url = new URL("http://localhost:8000/myfile");

            System.out.println("Calling Iface");

                Iface callInterface;

            int retval = callInterface.checkLink(url);      

            System.out.println("retval ="+retval);
        }
    }

Есть разница?


person user489152    schedule 20.07.2011    source источник
comment
Есть ошибка? или это просто обзор кода?   -  person talnicolas    schedule 20.07.2011
comment
Я думал, что наткнулся на рецензию на книгу   -  person Bohemian♦    schedule 20.07.2011


Ответы (5)


Технически ни один из опубликованных вами примеров кода не должен работать.

Ключевое слово protected указывает Java разрешать доступ к этой переменной классам только в том случае, если они расширяют класс Iface. Вы не расширяете класс в вызывающем коде, поэтому ни один из подходов к использованию метода не должен компилироваться, если метод не public.

Имейте в виду, что создание метода static означает, что вызывающим абонентам нужно будет использовать класс Iface напрямую, что делает невозможным использование наследования классов. Поэтому, если вы когда-нибудь захотите иметь другой класс, расширяющий Iface и переопределяющий реализацию checkLinks, вы захотите сделать этот метод нестатическим.

Если метод нестатический, вы можете использовать его следующим образом:

Iface callInterface = new Iface();
int retval = callInterface.checkLink(url);   

Вы также можете захотеть провести некоторое исследование фабричного шаблона и шаблона внедрения зависимостей, которые дадут вам больше гибкости в определении того, какую конкретную реализацию Iface вы хотите использовать.

person StriplingWarrior    schedule 20.07.2011
comment
: Protected означает, что только подклассы и классы в одном пакете могут получить к нему доступ. Итак, когда я использую класс Iface в приложении в том же пакете, он должен работать правильно? Потому что я только что протестировал свой код, и он работает ... - person user489152; 20.07.2011
comment
@ user49152: Это правда. Я предположил, что вызывающий код находится в другом пакете. Ключевое слово protected лучше всего использовать, когда вы ожидаете, что кто-то расширит ваш класс. В противном случае, если вы не укажете никаких ключевых слов доступа, уровень доступа по умолчанию позволит другим классам в том же пакете получать доступ к методу, не позволяя подклассам его в других пакетах использовать его. См. download.oracle.com/javase/tutorial/java/javaOO/ < / а> - person StriplingWarrior; 20.07.2011

Вызов статических методов через экземпляр и через класс функционально эквивалентны в Java. Следующий:

Iface.checkLink(<url>);

функционально эквивалентен

Iface foo = new Iface();  // or Iface foo;   but with the caveats below
foo.checkLink(<url>);

Однако учтите, что последнее не рекомендуется, поскольку оно сбивает с толку и не нужно. Можно утверждать, что это разрешено только из-за ошибка разработчиков языка Java.

Предостережение: в вашем примере вы не инициализируете свою Iface переменную. Вы по-прежнему можете вызывать статические методы через эту переменную, однако вы, вероятно, столкнетесь с проблемами в дальнейшем, если будете использовать ее для чего-либо, кроме статических методов (что вам не следует делать в первую очередь!).

Фактически, вам, вероятно, следует пойти еще дальше, чтобы сделать этот класс неустановленным, поскольку он выглядит как служебная программа. класс только со статическими методами.

person Daniel DiPaolo    schedule 20.07.2011
comment
Я согласен с тем, что ты не должен этого делать. Я забыл упомянуть об этом в своем ответе. - person Bart Vangeneugden; 20.07.2011
comment
Итак, обучение состоит в том, что я должен сделать свой класс не-экземпляром. Или, если я этого не сделаю, по крайней мере инициализируйте его, как указано выше. Но все же рекомендуется вызывать статический метод через класс. - person user489152; 20.07.2011
comment
@ user489152 да, именно так, в случае класса, который используется специально для размещения только статических методов, вы должны выполнить шаги в Статический класс Java?. И да, определенно вызывать только статические методы через класс. - person Daniel DiPaolo; 20.07.2011
comment
@Daniel DiPaolo: Конечно, если мне придется удалить это статическое ключевое слово из метода checkLink по причинам, указанным StriplingWarrior в его ответе, я создам экземпляр класса, как ваш последний подход - person user489152; 20.07.2011
comment
@ user489152 да, и вы, конечно же, захотите не делать его нестационарным. - person Daniel DiPaolo; 20.07.2011

Да, делая это: Iface callInterface; вы создаете экземпляр класса Iface и, следовательно, резервируете некоторое пространство в памяти. Тем не менее, вы все еще выполняете статический метод, поэтому вы не можете использовать какие-либо методы / атрибуты экземпляра.

Так что в плане исполнения разницы не будет. Что касается памяти / сборки мусора, будет.

person Bart Vangeneugden    schedule 20.07.2011
comment
Это не экземпляр объекта, пока вы не создадите объект и не создадите ссылку на него ... Это просто переменная этого типа. - person Yochai Timmer; 20.07.2011
comment
ах да, ты прав. Он не называл конструктора. Разве это не создает его в стеке, а не в куче? - person Bart Vangeneugden; 20.07.2011
comment
Поскольку для переменной никогда ничего не устанавливается, JIT, несомненно, оптимизирует это. Для переменной не будет зарезервировано место в стеке. - person StriplingWarrior; 20.07.2011
comment
@StriplingWarrior: Значит, поскольку я не вызывал конструктор для Iface, для него не будет места в стеке? - person user489152; 20.07.2011
comment
@ user489152: Поскольку вы не ничего назначили переменной callInterface, выделенного пространства стека не будет. Поскольку вы не вызывали конструктор, выделенного места в куче не будет. - person StriplingWarrior; 20.07.2011

Конечно, разница есть.

Статические методы не являются членами объекта, они принадлежат классу.

Итак, если checkLink() является статическим, вы должны вызывать его из самого класса: IFace.checkLink().

Вызов его из ссылки на объект будет работать, но логически это неправильное значение. Потому что метод не принадлежит объекту и не будет работать с фактическим состоянием объекта.

person Yochai Timmer    schedule 20.07.2011

Думаю, ваш вопрос был бы более точным, например «Что такое статика?».

Для меня просто «статика» означает, что эти переменные существуют только один раз для каждого класса, все остальные находятся в каждом объекте, происходящем из этого класса.

person Xote    schedule 20.07.2011