I believe that you might be confused with regard to how C# version works:
class A {
public void NonVirt() { Console.Out.WriteLine("A:NonVirt"); }
public virtual void Virt() { Console.Out.WriteLine("A:Virt"); }
}
class B : A {
public void NonVirt() { Console.Out.WriteLine("B:NonVirt"); }
public override void Virt() { Console.Out.WriteLine("B:Virt"); }
}
class Program {
static void Main(string[] args) {
A x = new B();
x.NonVirt();
x.Virt();
}
}
This will output
A:NonVirt
B:Virt
So even in C#, you need to make method virtual if you want to call the derived implementation.
If method must be implemented in all non-abstract subclasses this means that you need to call them through base class pointer. This in turn means that you need to make them virtual, same as in C# (and likely in Java, but I am not sure)
Btw, price of virtual call is a few nanoseconds on modern CPUs, so I am not sure if it is worth it but lets say that it is.
If you want to avoid the cost of virtual call, you should use compile time polymorphism via templates