Ваш вопрос о методе print ()? Это работает, потому что имя вашей переменной «скрывает» имя типа, поэтому, когда вы делаете B.print (), он смотрит на переменную B, которая является экземпляром класса B.
Вы действительно не должны называть вашу переменную тем же именем, что и класс, по крайней мере, не в том же регистре. Для вас все будет яснее, если вы переименуете переменную, даже если просто "b". Итак:
public class B{
public void print(){
}
public static void main(String[] args){
B b = new B();
b.print(); // This works
B.print(); // this fails
}
}