Причиной исключения является то, что класс, полученный при вызове
list.getClass()
в строке
System.out.println("size = " + list.getClass().getMethod("size").invoke(list));
возвращает фактический тип - java.util.Collections $ SynchronizedCollection. Класс SynchronizedCollection оказывается внутренним классом класса Collections, к которому вы не можете получить доступ, отсюда и исключение.
Лучший способ обойти это исключение - вызвать метод size в более подходящем классе / интерфейсе - обычно это класс реализации (поскольку он определенно содержит объявление или определение метода), но в нашем случае мы необходимо вызвать size () для открытого типа, учитывая, что obj.getClass () вернул непубличный тип. В частности, нам нужно вызвать size () в интерфейсе java.util.Collection (super) или в интерфейсе java.util.List.
Следующие операторы выведут «size = 1» в консоли:
System.out.println("size = " + Collection.class.getMethod("size").invoke(list));
System.out.println("size = " + List.class.getMethod("size").invoke(list));
Обновление
Если вам было интересно, синхронизирован ли метод size (), вызванный с помощью отражения, ответ - да, он синхронизирован. Несмотря на вызов метода size () для супертипа - Collection / List, метод size () во внутреннем классе SynchronizedCollection вызывается, и это происходит с синхронизацией. Это - деталь реализации, гарантированно работающая, так как коллекция упакована.
Кроме того, не рекомендуется использовать отражение, когда супертип - интерфейс Collection содержит метод size () .