#java #output-buffering
#java #буферизация вывода
Вопрос:
Работаю над этой библиотекой с одним классом, где мне нужно отключить буферизацию в stderr и stdout, если клиент импортирует этот класс, используя что-то вроде
// stderr
FileOutputStream fderr = new FileOutputStream(FileDescriptor.err);
// stdout
FileOutputStream fdout = new FileOutputStream(FileDescriptor.out);
// stderr buffer of size 1
BufferedOutputStream errBuf = new BufferedOutputStream(fderr, 1);
// stdout buffer of size 1
BufferedOutputStream outBuf = new BufferedOutputStream(fdout, 1);
// add more features and functionality to stderr and stdout
PrintStream errStream = new PrintStream(errBuf);
PrintStream outStream = new PrintStream(outBuf);
// update stderr and stderr
System.setErr(errStream);
System.setOut(outStream);
Наткнулся на статические инициализаторы, но, к сожалению, они запускаются только в определенных обстоятельствах, ни один из которых меня не интересует. Есть ли в Java какой-либо способ запустить приведенный выше код только путем импорта содержащего класса (т. Е. Только оператора import; Без вызова каких-либо методов и т. Д.)?
Комментарии:
1. Я думаю, вам придется изучить аннотации, возможно, написать свои собственные.
2.
import
инструкции не оказывают никакого влияния на время выполнения, они служат компилятору только для разрешения имен. Но даже если бы это сработало, это была бы ужасная идея, потому что IDE помечает и автоматически удаляет неиспользуемые операторы импорта.
Ответ №1:
Вы смотрите не в то место.
Если вы хотите, чтобы ваше приложение отправляло все сообщения stdout / stderr в определенный поток; тогда вы «просто» хотите управлять этим на уровне «запуска JVM». Другими словами: вы должны изучить способы управления JVM как можно раньше.
Вы не хотите, чтобы это перенаправление выполнялось, когда некоторые из ваших классов «импортируются»; вы хотите иметь надежный способ прямого указания JVM при запуске сделать это.
Но, конечно: действительно разумный способ делать такие вещи — использовать структуру ведения журнала, которая позволяет гораздо лучше контролировать происходящее. Ведение журнала в stdout / stderr — это, во-первых, не очень хороший подход!
Редактировать: учитывая тот факт, что речь идет о «тренировочных колесах» для учащихся; затем просто поместите статический метод настройки в некоторые из ваших библиотечных классов (в идеале, используя строки, которые обозначают имена файлов, куда должен идти stdout / stderr); и проинструктируйте своих учеников вызывать этот метод первым делом вих основные методы.
Комментарии:
1. На самом деле это педагогически мотивировано, когда мы предоставляем эту библиотеку в качестве обучающих колес в начале. Не то чтобы мы обесценивали изучение потоковой буферизации, скорее, мы не хотим, чтобы учащиеся сталкивались / заботились о буферизации, особенно в начале , для простоты. По той же причине платформа ведения журнала, вероятно, также не подходит для нас. Но спасибо за ввод!
2. Похоже, что нет более простого способа! Спасибо!
Ответ №2:
Импорт используется только во время компиляции.
Вы говорите, что статические инициализаторы не представляют интереса. Однако статические инициализаторы запускаются при загрузке вашего класса. Обойти это невозможно, вы не можете запускать код из своего класса без его загрузки, поэтому я бы сказал, что статические инициализаторы — это именно то, что вам нужно.
Клиент может загрузить класс без его создания, например, с помощью Class.forName
Пример
public class Foo
{
static
{
System.out.println("Class foo loaded");
}
}
// different file...
public class Client
{
static
{
try {
Class.forName("Foo");
}catch (ClassNotFoundException e) {
// TODO
}
}
public static void main (String args[]) {
// Nothing to do in this demo. The static intitizlier in
// this class causes Foo to be loaded and thus invokes Foo's
// static initializer
}
}