I have a huge (parent) POJO which is being used in some component. The POJO has individual fields as well as nested POJOs as well. Is it possible to determine what all fields/ nested fields from this POJO are being accessed in that component?
I was thinking about JUnits/ aspects but not sure if either would work. I've tried looking through SF/ and Google but could not find any relevant thread for this thing.
Say following is a sample POJO:
public class Student {
private String name;
private Date date;
private Subject subject;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
It has three fields name, date and subject, not all of which would be in use in my component. So I need to determine which are actually being used.
Edit:
Thanks Sharon for pointing out that the getter/setters were protected. I had just generated the class on the fly for the purpose of question and didn't notice the issue. Corrected now.
How the class is initialised: For the purpose of the component, objects will be created from Json/XML data and would have only getters being called.
As for static vs runtime analysis, I'd prefer to achieve it through static code analysis if that's possible otherwise runtime also is fine with me if that's easier.
As for using Decorator pattern, do we have anything without requiring existing code change? That's why I was thinking if JUnits could do this.
First of all, it is odd to see getter/setter methods that are protected. seems to me they need to be public?
Anyway, I would utilize the Decorator design pattern.
From the linked article:
The decorator design pattern allows us to dynamically add
functionality and behavior to an object without affecting the behavior
of other existing objects in the same class.
So, our decorated Student should inherit from the target class. All methods can log their usage and call super to invoke target operation. You didn't say how Student
is initialized, but anyway, you will want to modify that to create instances of LogUsageStudent
public class LogUsageStudent extends Student {
protected String getName() {
// log usage of getName()
return super.getName();
}
// etc
}
Related
Just getting my head around the Builder pattern and I have a few (noob) questions. Mainly, why can't we just simplify the creation of a builder object?
Instead of this:
public final class Foo {
private final String name;
private final String description;
private Foo(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public static class Builder {
private String name;
private String description;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setDescription(String description) {
this.description = description;
return this;
}
public Foo build() {
return new Foo(name, description);
}
}
}
//Use it
Foo f = new Foo.Builder().setName("test").setDescription("description").build();
Why not just use this?
public final class Foo {
private String name;
private String description;
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Foo setName(String name){
this.name=name;
return this;
}
public Foo setDescription(String description){
this.description=description;
return this;
}
}
//Use it
Foo f = new Foo().setName("test").set("description");
I see maybe the first one is used when you want to build an immutable object, but other than that why can't I just use the second one instead? It's far simpler. Please provide examples as much as possible.
Using your Second approach , i will be able to create a Object by doing.
Foo f = new Foo().setDescription("description");
Which means, We java created a object in your system without a name.
If we take another example which will be must self explanatory .
Employee emp = new Employee ().setDescription("manager");
Which means i hired a manager in a company without even know name.
Basically with Build() , we can also make sure all the required member variable are provided while creating a object. We can even do basic vaidation if needed.
public Foo build() {
if(name == null){
throw Exception();
else
return new Foo(name, description);
}
The builder pattern is useful when there are operations that are valid during construction that are not valid once the object is built.
Yes, this is most obviously the case for building immutable objects, but it also applies very often when only some aspects of the object are immutable. Common examples are:
Often the identifier for an object (a person's name, for example) is specified during construction, but is not allowed to change after that;
Injected dependencies, like the database to use, the log to use, etc., are often not allowed to change after construction;
Factories and strategies are often not allowed to change after construction, because the object expects consistency across all their outputs.
Also, sometimes a setter on a valid object would have an effect, like dispatching an event, for example, that you don't want to happen during construction. You can sometimes get around that via complicated rules like "don't attach listeners until you're finished setting stuff up", but complicated rules are to be avoided.
Your way is "JavaBeans Patterns", From effectice java item2:"JavaBean Patterns" construction is split across multiple calls, a
JavaBean may be in an inconsistent state partway
through its construction. The class does not have the option of
enforcing consistency merely by checking the validity of the
constructor parameters. Attempting to use an object when it’s in
an inconsistent state may cause failures that are far removed from
the code containing the bug and hence difficult to debug. A related
disadvantage is that the JavaBeans pattern precludes the
possibility of making a class immutable and
requires added effort on the part of the programmer to ensure
thread safety. "Builder Pattern" is thread safe and more readable.
you can use lombok #Builder annotation to make a class "Builder Pattern".
I have a class that may have several enums within it.
Each enum is supposed to have a string value associated with each entry.
In order to achieve this, I have added a parametrized constructor,a supporting string class member and overridern the toString method.
However one can see that 50% of the code between my two enums are same. It's just the code to support mapping strings to the Enum values.
How can I move this code to a common place and avoid code duplication?
Edit: Use case is to easily obtain "New York" when I write America.STATES.NY.
Here's what I tried,
1) I tried using a common interface, but the constructors are different.
2) I tried using inheritance, but enums cannot be inherited
public class America {
public enum STATES {
NY("New York"), CA("California");
String displayName;
STATES(String displayName) {
this.displayName = displayName;
}
#Override
public String toString() {
return this.displayName;
}
}
public enum PROVINCES {
ON("Ontario"), QU("Qubec");
String displayName;
PROVINCES(String displayName) {
this.displayName = displayName;
}
#Override
public String toString() {
return this.displayName;
}
}
}
A typical phrase I like to use is "data isn't a part of behavior, and doesn't belong in the code". To be clear (and from my experience), it's much easier to adopt or translate a system that relies on the data for it being loaded from something rather than representing the data in hard-coded values.
public class Region {
private final String name;
public Region(String name) { this.name = name; }
public String getDisplayName() { return this.name; }
public String toString() { return getDisplayName(); }
}
public class Country {
//keeps a map/list of "regions", whether states or provinces or some other type
public Region getRegion(Object key); //lookup a region based on some key, I'll use strings here
}
Country america = /* a country supplied from somewhere */;
String name = america.getRegion("NY").getDisplayName(); //"New York"
This type of approach, while sub-optimal for hard-coded references in your code (like getRegion("NY")), is much more forgiving when you need to modify the data later or make a reference which is loaded from elsewheres (e.g. a user-supplied Region or lookup name). If you use a database, you can keep your code up-to-date without ever having to change the project, just the database itself. And in the end, since all of this data-related information is stored elsewheres, the overall amount of code to handle is vastly reduced.
You can also later add in something to support determining whether a given administrative region is a state or province or something else (which I think an enum is great for):
public enum RegionType {
STATE, PROVINCE, ADMIN_REGION, OTHER,
;
}
You can implement an EnumUtils class and add a static instance of it to every enum class. I implemented an example here: https://stackoverflow.com/a/48199147/7949301.
We always say that, Encapsulation keeps data and functionality safe from the outside world.
So its a protective wrapper around the class and the code can be saved from unauthorized access by outer world.
But what if,
I declare one variable with public modifier will it break Encapsulation ?
Encapsulation in Java is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.
public class EncapTest {
private String name;
private String idNum;
private int age;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getIdNum() {
return idNum;
}
public void setAge( int newAge) {
age = newAge;
}
public void setName(String newName) {
name = newName;
}
public void setIdNum( String newId) {
idNum = newId;
}
}
so that all your methods and variable should be private
In my idea modifiers absolutely supports Encapsulation. Maybe you just violate Information Hiding.
Encapsulation is not information hiding. Information hiding is a more fundamental technique than encapsulation. We should clarify between Encapsulation and Information Hiding. (see the reference)
Encapsulation is a technique for expressing the boundaries of
those modules.
Suppose that we have an attribute in our class and we need to set some values from external the class. We can not define it as public. We can not define it as protected too (see this question), the only way to define this types of conditions is defining some methods (or some modifiers in very simple interface). In this case we Encapsulate it.
So what is the difference between a public attribute and a private attribute with modifiers?
In a very big projects, we can add some other conditions to modifiers without any changes to other parts of project (the OCP of SOLID).
Finally: In some cases we need to set some values from outside the class to attributes. So sometimes we need to use modifiers and it is the encapsulation way to access the fields. We can not define the fields as public or protected in OOP.
First of all, let's see what encapsulation really is.
Encapsulation is one of the four OOP concepts.
In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.
So making a class variable public it's not encapsulation anymore.
Let's see some real usages of encapsulation:
By encapsulating, you force yourself and other developers to access that variable through their getters and setters. Let's be honest, it's the same thing as if the field was public, right?
But what if you add some logic to the setters?
public class User {
private String username;
private String password;
// username getter and setter not displayed in this example.
public void setPassword(String password) {
this.password = someCoolHashingMethod(password);
}
public String getPassword() {
return this.password;
}
}
Do you see what's happening there? You force the password to be stored as a hash instead of clear. (There are many ways to protect a password but we'll stick to this dummy example for now).
Another real use for encapsulation is that you can change the name of the variable without changing the code everywhere in your application.
So you if you change it's name and it's not encapsulated, you will have to go everywhere you used it, modified it, to change there aswell. So a project level refactorization is needed. But if it's encapsulated, you used getters and setters everywhere! That means you just need to change it there only. Example:
public class User {
private String username;
private String pass; // <---- notice the new name
// username getter and setter not displayed in this example.
public void setPassword(String password) {
this.pass = someCoolHashingMethod(password); // <---- notice the new name
}
public String getPassword() {
return this.pass; // <---- notice the new name
}
}
Hope this answered a little bit more than your question really was.
I have few issues/doubts to fill values in a HashMap
I want a HashMap to accept "Student" as key and "Details" as value.
Since key to a hashMap should be immutable I have some doubts how can this be dealt if
Student class did not cloneable
Student class has reference to which in turn have reference to "Lab"
public class Student {
private String id;
private String name;
private Department dept;
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
public Department getDepartment()
{
return this.dept;
}
}
public class Department {
private String deptId;
private Lab lab;
public Department(String deptId, Lab lab)
{
this.deptId=deptId;
this.lab=lab;
}
public void setLab(Lab lab)
{
this.lab=lab;
}
}
public class Lab {
private String labId;
private String labName;
public Lab(String labId, String labName)
{
this.labId=labId;
this.labName=labName;
}
}
public class StudentDetails
{
private String fatherName;
private String address
public StudentDetails(String fatherName, String address)
{
this.fatherName=fatherName;
this.address=address;
}
}
public class StudentMaintainer {
public static void main(String[] args)
{
StudentDetails stDetails= new StudentDetails("John","Mumbai");
Lab lab= new Lab("100","CS");
Department dept= new Department("900", lab);
Student st = new Student("3000",dept);
Map<Student,StudentDetails> studentMaintainer= new ArrayList<>();
studentMaintainer.put(st,stDetails);
}
}
Now Even if Student is cloneable, I can get reference of Department and call setLab() which changes the StudentObject. (Am I wrong?)
Now if Department and Lab are from 3rd party jars, how can I use Student Object in my Map if Student hashCode is (primeNumber+Student.id+Department.id+Lab.id).hashcode() [just some weird case];
Immutability has nothing to do with Cloneable as far as I understand it, and in fact just the opposite. Immutability has more to do with declaring the class final and using immutable fields, non-overridable methods, no setter methods, getter methods that return deep copies of fields or immutable fields, etc... Please read A Strategy for Defining Immutable Objects for more on this.
Also your code has a pseudo-constructor:
public void Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
A true constructor should not be declared to return anything, not even void. Better would be:
// note the difference?
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
Also, your Student class should properly override equals and hashCode if it is to work well as a key for a HashMap.
Now Even if Student is cloneable, I can get reference of Department
and call setLab() which changes the StudentObject. (Am I wrong?)
You are correct. This can happen, and can cause your Student class to appear to be mutated. For an instance of Student to be immutable, you must not be able to modify any of its fields[0]. That includes calling something like a setter method on one of its fields.
Now if Department and Lab are from 3rd party jars, how can I use
Student Object in my Map if Student hashCode is
(primeNumber+Student.id+Department.id+Lab.id).hashcode() [just some
weird case];
That is a very good question. You obviously can't just change the classes to be immutable, since you don't have control over them, so you may have to get a bit creative. Possible solutions:
if the third party objects you want to use are interfaces, you could implement the interface with your own type, where the body of every mutator method throws an exception (think e.g. java.util.Collections.unmodfiableList). This has the benefits that you can still refer to the third party class in your codebase, but the drawback that calling mutator methods will fail at runtime, rather than at compile time.
write adapters in your own codebase, like this:
public final class MyImmutableDepartment {
private final MyImmutableLab lab;
private final String departmentId;
public MyImmutableDepartment(Department thirdPartyMutableDepartment) {
this.departmentId = thirdPartyMutableDepartment.getId();
this.lab = new MyImmutableLab(thirdPartyMutableDepartment.getLab());
}
// getters and the MyImmutableLab class left as an exercise
}
This has the advantage that you know at compile time, the classes cannot be mutated.
The downside in both approaches is that you basically have to mirror every class from the third party library, to ensure they're immutable.
I don't think there's any other alternatives.
[0] there are some cases where this is possible, and can be used for internal caching, but it's a decent guideline to stick to when learning.
Student does not need to be immutable! Specifically, the requirement is that the behavior of equals/hashCode doesn't change when the key is in the HashMap.
This can be accomplished in three ways:
Don't implement equals/hashCode. If you use the default reference equality, it doesn't matter how you mutate the key. To clarify intent, override those methods, explicitly call super.equals, and make them final.
Don't include any fields that will mutate in your calculation of equals/hashCode. Or, if the properties of a field may change but not the reference, use reference equality (==) instead of field.equals() and call System.identityHashCode(field) instead of field.hashCode()
Don't mutate the object while it is used as a key in the HashMap. A bit dangerous, but works fine if references aren't held by code beyond your control. Document the requirement.
But, in your concrete example, each student has an id. Why would you use any other properties when implementing equals/hashCode.?
I'm new to Java, but have some OOP experience with ActionScript 3, so I'm trying to migrate relying on stuff I know.
In ActionScript 3 you can create getters and setters using the get and set keywords, meaning you create a method in the class and access data through a property of an instance of that class. I might sound complicated, but it's not. Here's an example:
class Dummy{
private var _name:String;
public function Dummy(name:String=null){
this._name = name;
}
//getter
public function get name():String{
return _name;
}
//setter
public function set name(value:String):void{
//do some validation if necessary
_name = value;
}
}
And I would access name in an object as:
var dummy:Dummy = new Dummy("fred");
trace(dummy.name);//prints: fred
dummy.name = "lolo";//setter
trace(dummy.name);//getter
How would I do that in Java?
Just having some public fields is out of the question.
I've noticed that there is this convention of using get and set in front of methods, which I'm OK with.
For example,
class Dummy{
String _name;
public void Dummy(){}
public void Dummy(String name){
_name = name;
}
public String getName(){
return _name;
}
public void setName(String name){
_name = name;
}
}
Is there an equivalent of ActionScript 3 getter/setters in Java, as in
accessing a private field as a field from an instance of the class, but having a method for implementing that internally in the class?
Nope. AS3 getters and setters are an ECMAScript thing. In Java, you're stuck with the getVal() and setVal() style functions--there isn't any syntactic sugar to make things easy for you.
I think Eclipse can help auto-generating those types of things though...
Your Java code is fine, except that you would, want to make _name private.
There are no get and set keywords in Java as in your AS3 example. Sorry, it doesn't get better than what you're doing already.
Corrected code:
class Dummy {
private String _name;
public void Dummy() {}
public void Dummy(String name) {
setName(name);
}
public String getName() {
return _name;
}
public void setName(String value) {
_name = value;
}
}
Sadly, no, there isn't the equivalent language-level support in java.
The get* and set* patterns though are so established in java culture that you'll find strong IDE support for them (e.g., eclipse will make them for you automatically), and if you're working in something that uses the expression language first made for jsps (EL), then you'll be able to use the property notation to access getters and setters.
I would consider not having the getter or setter as they don't do anything in your case except make the code more complicated. Here is an example without getters or setters.
class Dummy {
public String name;
public Dummy(String name) { this.name = name; }
}
Dummy dummy = new Dummy("fred");
System.out.println(dummy.name);//getter, prints: fred
dummy.name = "lolo";//setter
System.out.println(dummy.name);//getter, prints: lolo
IMHO Don't make things more complicated than you need to. It so often the case that adding complexity will suffer from You-Aint-Gonna-Need-It
An IDE-independent way is to use Lombok, an annotation-based library that generates getters, setters, and even equals() and hashcode(). It does this for the compiler, but not in the source file, so you don't have to look at the methods, just use them.
In Java, the only option you have without exposing the internals of your object is to make your own getters and setters as you have in your example.
The convention is to prepend get or set in front of the field which is being altered. So, as in your example, the field name would have getName and setName methods as their corresponding getter and setter, respectively.
Also before adding setters and getters, it might be a good idea to ask yourself why are you exposing the internal data of the Object in question.
I suggests you read this article -
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html