I am new to Kotlin and I have the following doubt -
Using the Java to Kotlin converter (this Link), I converted the following Java code to Kotlin.
Java Class:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
Generated Kotlin Class:
class Person(name:String, age:Int) {
var name:String
var age:Int = 0
init{
this.name = name
this.age = age
}
}
But I don't understand how the Java Code and the generated Kotlin code are equivalent because the visibility modifiers of the class data members change from private(in Java) to public(in Kotlin).
I believe that if the visibility modifiers are preserved(the data members are declared private in Kotlin), getters and setters will have to be created in Kotlin too and only then should they be equivalent.
in Kotlin, it implicitly creates getters and setters for the fields (which you had in Java as well). As these are public, the fields themselves become effectively public.
Effectively your Java code with the simplistic getters and setters was the equivalent of having public fields because of the nature of the getters and setters (no validation etc.).
Had your setters done for example null checks and thrown IllegalArgumentExceptions, the code'd have been different.
public member in Kotlin is not equivalent to public member in Java. It is still invisible to public when accessed by other Java class. You need to add #JvmField in front of the var to make it equivalent to public member in Java.
For Kotlin class Foo { var bar = 1 }. To access it by Java, new Foo().bar does not compile. You have to use new Foo().getBar(). bar is still a private member with getter and setter in the perspective of Java.
Changing the Kotlin code to class Foo { #JvmField var bar = 1 }, it truly becomes a public member in Java. You can then access it by Java using new Foo().bar
There are getters, in cases with val, setters in case var. Access to the field for reading or changing always passes through them.
You can notice them when using the Kotlin class from the java class.
If getters or setters describe the default behavior, then point them in the code does not make sense.
PS: if you convert your java class to Kotlin class, will like
class Person(var name: String?, var age: Int)
Related
Need some help here! I have a Java Rest API which is getting data from a .net endpoint and passing it on to the UI. The JSON properties are in capital case and I want to convert them in JAVA before sending it to the UI. Any pointers on this?
In java, I have a class like below:
public class Person {
#JsonProperty("Name")
private String name;
#JsonProperty("Age")
private int age;
}
I am using #JsonProperty as keys in .net are starting with capitalCase. How can I convert this back before sending it to the UI in Java?
Thanks for the help!
Create another class with the same structure and use there other names that you want. Something like this:
// Class to read .NET object
public class Person {
#JsonProperty("Name")
private String name;
#JsonProperty("Age")
private int age;
}
// Class to represent the object in Java REST API
public class Person {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
}
// Class to represent the object in Java REST API,
// in case you use some standard library that
// uses property names for JSON as is
public class Person {
private String name;
private int age;
}
Of course you should put these classes into different packages.
Your code can look as follows:
xxx.dotnet.Person dotnetPerson = doSomethingViaDotNet(...);
yyy.rest.Person restPerson = new yyy.rest.Person();
restPerson.setName(dotnetPerson.getName());
restPerson.setAge(dotnetPerson.getAge());
...
return restPerson;
If you decide to use MapStruct, your code may looks as follows:
#Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper( PersonMapper.class );
yyy.rest.Person dotnetToRest(xxx.dotnet.Person dotnetPerson);
}
Since all attributes have the same names and types you don't need anything else in your mapper.
MapStruct will generate a class that implements this interface. Usage will be as follows:
restPerson = PersonMapper.INSTANCE.dotnetToRest(dotnetPerson);
I have got a question.
Should I create getter and setter methods inside abstract class? The below example contains these methods inside abstract class which is extended by Individual class. Is it a good practice to have different variety on methods inside abstract class? Should I be overriding those methods inside Individual class? However it doesn't make sense for me to override those as these will not do anything different, just set and get different attributes. Any advice?
public abstract class Human {
private String name;
private String surname;
public Human(String name, String surname) {
this.name = name;
this.surname = surname;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
public class Individual extends Human{
private String dob;
public Individual(String name, String surname, String dob) {
super(name, surname);
this.dob = dob;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public void viewIndividual(){
System.out.println("First name of individual is: " + getName());
System.out.println("Surname of individual is: " + getSurname());
System.out.println("Date of birth of individual is: " + getDob());
}
}
Should I create getter and setter methods inside abstract class?
Yes, if a method is common to most expected implementations of an abstract class, it's perfectly fine to implement those methods in the abstract class. If it's really good to have getters and setters for the properties of your Human, it hard to say. The way you're currently using it, it doesn't make much sense, as you're mixing behavior aspects (viewIndividual) with data aspects (getters and setters) in one class. Given the code above you would be fine with protected members in the abstract class, and potentially setters to avoid code duplication in the implementations. But if you want to use your objects as Java-Beans, it's fine.
Is it a good practice to have different variety on methods inside abstract class?
You mean both, abstract and non-abstract methods? Yes, this is pretty standard. Take this example:
public abstract class Example {
public final void publicMethod() {
// do some preparations
internalMethod();
// do some cleanup
}
protected abstract void internalMethod();
}
Consumers of implementations of Example will only be able to access publicMethod and it is guaranteed that all needed preparations and cleanup tasks are executed without repeating this code over and over again in the implementations of Example as only internalMethod needs to be overridden.
Should I be overriding those methods inside Individual class?
No, definitively not. At least as long as you don't add additional functionality to the methods, abstract methods should not be overridden just for implementing them inside the instantiatable class.
In general you should be careful with inheritance as code tends to become very hard to understand, if you implement something in a deep type hierarchy. IMHO hierarchies start to become hard to use with a hierarchy level of 4-5 already, but this is probably heavily opinion based. There is the rule to prefer composition over inheritance to avoid over-exhaustive use of inheritance for simple utility stuff.
Creating immutable class using setter method from outside class.As i have a POJO Class Object creation may be done using setter method.How come it possible to make immutable using setter
Setters are mutators.
https://en.wikipedia.org/wiki/Mutator_method
I think you might be referring to a factory method?
https://www.tutorialspoint.com/design_pattern/factory_pattern.htm
Or maybe you have some hybrid thingo going on.
People more experienced then me would have better answers.
You can use the Builder Pattern. There you have a separate builder class with a kind of setter for each field. The final build() eventually creates the immutable object.
public final class Person {
private final String forename;
private final String surename;
private final int age;
private Person(String forename, String surename, int age) {
this.forename = forename;
this.surename = surename;
this.age = age;
}
public String getForename() {
return forename;
}
public String getSurename() {
return surename;
}
public int getAge() {
return age;
}
public static PersonBuilder createBuilder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String forename;
private String surename;
private int age;
private PersonBuilder() {
}
public PersonBuilder withForename(String forename) {
this.forename = forename;
return this;
}
public PersonBuilder withSurename(String surename) {
this.surename = surename;
return this;
}
public PersonBuilder withAge(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(forename, surename, age);
}
}
You can then create a Person instance like so:
Person person = Person.createBuilder().withSurename("Krueger")
.withForename("Freddy").withAge(47).build();
With a builder you have the best of both worlds. The flexibility of setters (including fluent API) and immutable objects at the end.
Edit:
Joshua Bloch stated in Item 15: "Minimize Mutability" in his book "Effective Java":
To make a class immutable, follow these five rules:
Don’t provide any methods that modify the object’s state (known as mutators).
Ensure that the class can’t be extended. [...]
Make all fields final. [...]
Make all fields private. [...]
Ensure exclusive access to any mutable components. [...]
To fulfill point 2 I added the final keyword to the above Person class.
According to this widely accepted definition of immutability a class with setters is per se not immutable because it violates point 1.
If think the intention to ask this question in an interview is to see wether the candidate is able to recognize the discrepancy in the question itself and how far goes the knowledge about immutability and the various alternatives to create instances of immutable classes (per constructor, per static factory methods, per factory classes, per builder pattern, ...).
basically I created a Person class and a constructor which sets the name,last name,age of the Person.all the properties of the class were set the private as it should be. I have made setters and getters for all the properties. On the main method I tried to override one of the setters just for practice reason. Its did draw an error saying Person.name not visible which means it cannot access private, Why this is happening, I mean if wasn't overriding the method it would have access. but if I set it to protected mode i will work.
Here is the code:
class Person {
private int age;
private String name;
private String last_name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public Person(int age, String name, String last_name) {
this.age = age;
this.name = name;
this.last_name = last_name;
}
}
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person per = new Person(15,"bb","Sb") {
public void setName(String name) {
this.name = "aaaa";
}
};
per.setName("asdfaf");
System.out.println(per.getName());
}
}
A private member is only accessible in the class in which it is declared.
You created an anonymous sub-class of Person and tried to access a private member of the super-class from the sub-class. This is never allowed.
When developers of a class wish to allow access to certain members of the class to its sub-classes, they set the acess level to protected.
You have created a class named Person and in the following lines you are trying to create an anonymous subclass:
Person per = new Person(15,"bb","Sb") {
public void setName(String name) {
this.name = "aaaa";
}
};
As mentioned in doc:
A subclass does not inherit the private members of its parent class
Here your anonymous subclass is trying to access private field name directly and so is the error. You can use getter/setter which are public. You can also check this related question on SO.
You cannot access private fields from outside your class, even if you are overriding it. You are basically defining a new subclass of Person in your main(), which isn't allowed access to the private field Person.name. However, it can access a protected field.
Basic idea behind overriding is to redefine existing functionality and give new definition to it. If you refer to documentation, private member variables are only accessible in it own class. That why it is not available in your anonymous sub-class implementation.
Note: Generally we do not override setter methods as they are not a functionality.
This is called encapsulation . You can not access private vars from other classes . you can find more description here
Is there, in Java, a way to add some fields and methods to an existing class?
What I want is that I have a class imported to my code, and I need to add some fields, derived from the existing fields, and their returning methods.
Is there any way to do this?
You can create a class that extends the one you wish to add functionality to:
public class sub extends Original{
...
}
To access any of the private variables in the superclass, if there aren't getter methods, you can change them from "private" to "protected" and be able to reference them normally.
Hope that helps!
You can extend classes in Java. For Example:
public class A {
private String name;
public A(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class B extends A {
private String title;
public B(String name, String title){
super(name); //calls the constructor in the parent class to initialize the name
this.title= title;
}
public String getTitle(){
return this.title;
}
public void setTitle(String title) {
this.title= title;
}
}
Now instances of B can access the public fields in A:
B b = new B("Test");
String name = b.getName();
String title = b.getTitle();
For more detailed tutorial take a look at Inheritance (The Java Tutorials > Learning the Java Language > Interfaces and Inheritance).
Edit: If class A has a constructor like:
public A (String name, String name2){
this.name = name;
this.name2 = name2;
}
then in class B you have:
public B(String name, String name2, String title){
super(name, name2); //calls the constructor in the A
this.title= title;
}
The examples only really apply if the class you're extending isn't final. For example, you cannot extend java.lang.String using this method. There are however other ways, such as using byte code injection using CGLIB, ASM or AOP.
Assuming this question is asking about the equivalent of C# extension methods or JavaScript prototypes then technically it is possible as this one thing that Groovy does a lot. Groovy compiles Java and can extend any Java class, even final ones. Groovy has metaClass to add properties and methods (prototypes) such as:
// Define new extension method
String.metaClass.goForIt = { return "hello ${delegate}" }
// Call it on a String
"Paul".goForIt() // returns "hello Paul"
// Create new property
String.metaClass.num = 123
// Use it - clever even on constants
"Paul".num // returns 123
"Paul".num = 999 // sets to 999
"fred".num // returns 123
I could explain how to do the same way as Groovy does, but maybe that would be too much for the poster. If they like, I can research and explain.