Хотел сделать попроще, но не принимает.
Вроде учел все пожелания из комментов к задаче.
Вывод такой у меня:
com.javarush.task.task36.task3606.data.second.HiddenClassImplSecond@610455d6
com.javarush.task.task36.task3606.data.second.HiddenClassImplFirst@511d50c0
com.javarush.task.task36.task3606.data.second.PackageAccessClass@60e53b93
package com.javarush.task.task36.task3606;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
/*
Осваиваем ClassLoader и Reflection
Аргументом для класса Solution является абсолютный путь к пакету.
Имя пакета может содержать File.separator.
В этом пакете кроме скомпилированных классов (.class) могут находиться и другие файлы (например: .java).
Известно, что каждый класс имеет конструктор без параметров и реализует интерфейс HiddenClass.
Считай все классы с файловой системы, создай фабрику - реализуй метод getHiddenClassObjectByKey.
Примечание: в пакете может быть только один класс, простое имя которого начинается с String key без учета регистра.
Требования:
1. Реализуй метод scanFileSystem, он должен добавлять в поле hiddenClasses найденные классы.
2. Реализуй метод getHiddenClassObjectByKey, он должен создавать объект класса согласно условию задачи.
3. Метод main не изменяй.
4. Метод getHiddenClassObjectByKey не должен кидать исключений.
*/
public class Solution {
private List<Class> hiddenClasses = new ArrayList<>();
private String packageName;
public Solution(String packageName) {
this.packageName = packageName;
}
public static void main(String[] args) throws ClassNotFoundException {
Solution solution = new Solution(Solution.class.getProtectionDomain().getCodeSource().getLocation().getPath() + "com/javarush/task/task36/task3606/data/second");
solution.scanFileSystem();
System.out.println(solution.getHiddenClassObjectByKey("hiddenclassimplse"));
System.out.println(solution.getHiddenClassObjectByKey("hiddenclassimplf"));
System.out.println(solution.getHiddenClassObjectByKey("packa"));
}
public void scanFileSystem() {
SearchFileVisitor searchFileVisitor = new SearchFileVisitor();
try {
Files.walkFileTree(Paths.get(packageName.substring(1)), searchFileVisitor);
} catch (IOException e) {
e.printStackTrace();
}
List<Path> filePaths = searchFileVisitor.getFoundFiles();
MyClassLoader classLoader = new MyClassLoader();
for (Path path: filePaths) {
Class clz = classLoader.load(path);
hiddenClasses.add(clz);
}
}
public HiddenClass getHiddenClassObjectByKey(String key) {
for (Class clazz : hiddenClasses) {
if (clazz.getSimpleName().toLowerCase().startsWith(key.toLowerCase())) {
try {
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
if (constructor.getParameterTypes().length == 0) {
Class[] interfaces = clazz.getInterfaces();
if (interfaces.length > 0) {
for(Class interfaze : interfaces) {
if (interfaze.getSimpleName().equals("HiddenClass")) {
constructor.setAccessible(true);
return (HiddenClass) constructor.newInstance(null);
}
}
}
}
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
return null;
}
class SearchFileVisitor extends SimpleFileVisitor<Path> {
private List<Path> foundFiles = new ArrayList<>();
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.toString().endsWith(".class")) {
foundFiles.add(file);
}
return super.visitFile(file, attrs);
}
public List<Path> getFoundFiles() {
return foundFiles;
}
}
public static class MyClassLoader extends ClassLoader {
public Class<?> load(Path path) {
byte[] b = null;
try {
b = Files.readAllBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
return defineClass(null, b, 0, b.length);
}
}
}