Can I override a static method?
Многие слышали, что вы не можете переопределить статический метод. Это правда - вы не можете. Однако можно написать такой код:
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
Это компилируется и выполняется просто отлично. Разве это не пример статического метода, который переопределяет другой статический метод? Ответ - нет - это пример статического метода, скрывающего другой статический метод. Если вы попытаетесь переопределить статический метод, компилятор фактически не остановит вас - он просто не делает то, что вы думаете.
Итак, какая разница?
Коротко , когда вы переопределяете метод, вы все равно получаете преимущества полиморфизма во время выполнения, а когда вы скрываете, вы этого не делаете. Так что это значит? Взгляните на этот код:
class Foo {
public static void classMethod() {
System.out.println("classMethod() in Foo");
}
public void instanceMethod() {
System.out.println("instanceMethod() in Foo");
}
}
class Bar extends Foo {
public static void classMethod() {
System.out.println("classMethod() in Bar");
}
public void instanceMethod() {
System.out.println("instanceMethod() in Bar");
}
}
class Test {
public static void main(String[] args) {
Foo f = new Bar();
f.instanceMethod();
f.classMethod();
}
}
Если вы запустите это, выход будет
instanceMethod () в Bar classMethod () в Foo
Почему мы получаем instanceMethod из Bar, но classMethod () из Foo? Разве мы не используем один и тот же экземпляр f для доступа к ним обоих?
Поскольку instanceMethod () - это (барабан, пожалуйста, ...) метод экземпляра, в котором Bar отменяет метод от Foo во время выполнения JVM использует фактический класс экземпляра f для определения того, какой метод запускать. Хотя f был объявлен как Foo, фактический экземпляр, который мы создали, был новым Bar (). Таким образом, во время выполнения JVM обнаруживает, что f является экземпляром Bar, и поэтому он вызывает instanceMethod () в Bar, а не в Foo. Так Java обычно работает, например, методами.
Однако с классомMethod (). поскольку (гм) это метод класса, компилятор и JVM не ожидают, что для вызова метода будет задействован фактический экземпляр. И даже если вы предоставите один (который мы сделали: экземпляр, упомянутый f), JVM никогда не будет смотреть на него. Компилятор будет рассматривать только объявленный тип ссылки и использовать этот объявленный тип для определения во время компиляции метода для вызова. Поскольку f объявлен как тип Foo, компилятор просматривает f.classMethod () и решает, что это означает Foo.classMethod. Не имеет значения, что экземпляр, присвоенный f, фактически является баром - для статических методов компилятор использует только объявленный тип ссылки. Это то, что мы имеем в виду, когда мы говорим, что статический метод не имеет полиморфизма во время выполнения.
Поскольку методы экземпляров и методы класса имеют это важное различие в поведении, мы используем разные термины - «переопределение», например, методов и «скрывать» для методов класса - различать эти два случая. И когда мы говорим, что вы не можете переопределить статический метод, это означает, что даже если вы пишете код, который выглядит как переопределяющий статический метод (например, первый Foo и Bar в верхней части этой страницы) - это не будет ведут себя как переопределенный метод. для более ссылки это
Чтобы, по крайней мере, начать «сворачивать голову», вот подход, который можно использовать, предполагая, что вы используете некоторый кодовый «язык» для доступа к базе данных SQL Server. Вот некоторый простой для понимания классический ASP-код для вычисления переменной FractionToUse, который затем можно было бы использовать для умножения в операторе SQL:
FirstDayOfCurMonthDate = DateSerial(Year(Date()), Month(Date()), 1)
CurrentDate = Date()
FinalDayOfCurMonthDate = DateSerial(Year(Date()), Month(Date()) + 1, 1 - 1)
DaysInCurMonthRemaining = DateDiff("D", CurrentDate, FinalDayOfCurMonthDate) + 1
DaysInCurMonthTotal = DateDiff("D", FirstDayOfCurMonthDate, FinalDayOfCurMonthDate) + 1
FractionToUse = DaysInCurMonthRemaining / DaysInCurMonthTotal
Я думаю, что наткнулся на ответ, который искал ... он немного неуклюжий, но достигает того, к чему я стремился - сузить даты со дня выполнения запроса до конца этого месяца: [110 ]