Search code examples
javaclassencapsulation

Edited Access control exercise - java


I need to print the attributes from TestCar class by creating a public hackCar method in class Terminal. The hackCar method needs to take a TestCar as a parameter and print the attributes of TestCar. The caveat for this assignment is that I cannot touch anything in the TestCar class.

I am still struggling with printing the two private attributes in TestCar. How can I print the two private attributes from TestCar class by using the TestCar object as the parameter in the hackCar method?

Story class:

class Story {
    public static void main(String args[]) {
        TestCar testCar = new TestCar();
        Terminal terminal = new Terminal();
        terminal.hackCar(testCar);
    }
}

class Terminal {

    public void hackCar(TestCar other) {

        System.out.println(other.doorUnlockCode);

        System.out.println(other.hasAirCondition);

        System.out.println(other.brand);

        System.out.println(other.licensePlate);
    }
}

class TestCar {

    private int doorUnlockCode = 602413;
    protected boolean hasAirCondition = false;
    String brand = "TurboCarCompany";
    public String licensePlate = "PHP-600";
}

Thanks!


Solution

  • Since, you can't touch the class TestCar, you can't set any Getter methods to access the private members of the class from outside the class.

    So, the only way to do it (access the Private members of the class without using any Getter Functions), is to use the Reflection API in java.

    Here is the code,

    public void hackCar(TestCar other) {
    
            Field f = other.getDeclaredField("doorUnlockCode");  /*here we create the object of the desired field*/
    
            f.setAccessible(true);  //here, we set its access to true
    
            System.out.println(f.get(obj));   /*here, we use the field object to get its value*/
    
            Field f1 = other.getDeclaredField("hasAirCondition");
    
            f1.setAccessible(true);
    
            System.out.println(f1.get(obj));
    
            Field f2 = other.getDeclaredField("brand");
    
            f2.setAccessible(true);
    
            System.out.println(f2.get(obj));
    
            System.out.println(other.licensePlate);  /*this can be accessed directly since the access specifier for the field is "public"*/
        }
    

    You can modify your HackCar method this way.

    You will need to import these.

    import java.lang.reflect.Method;
    import java.lang.reflect.Field;
    import java.lang.reflect.Constructor;
    

    This is a solution to the above problem, but it has its own flaws. It causes Performance Overheads and also causes Security Problems as it violates the Abstraction principle of OOP.

    So, use this solution judiciously.

    NOTE - You can also access the fields that have their access specifiers protected or default, by defining a class (let's call it C) in the same package as the TestCar class, and using the member functions of the class C as the getter functions for the protected and default fields of the TestCar class.