Lets have these two getters in Kotlin:
data class Foo(var id: String){
val reference get() = Reference("Patient/$id")
}
data class Foo(var id: String){
fun getReference(){ return Reference("Patient/$id") }
}
Does the first one have some performance cons? I like it more, but I am not sure if they are built into same bytecode, or the first one adds more things, because I am basically delaring new variable and not just method.
In your example, they are equivalent behind the scenes (but obviously, you need different syntax for using the property vs. the method). Specifically, Kotlin will generate a backing field if any of the accessors use the field identifier, and the autogenerated get and set accessors do use field. So in order to avoid a backing field, you need to supply your own get accessor and (in the case of a var property) a set accessor, and none of them must use field.
Whether a property has a backing field or not, reading the property turns into a method call to get() behind the scenes, and if it's a var, assigning to the property turns into a method call to set().
Note that it's possible to get into weird situations with var if your accessors are inconsistent: var foo: Int = 3; get() = 42 will always return 42 when you read it, irrespective of the initial value and whatever you might assign to it, because you will get an autogenerated backing field since you omitted the setter, and that's what the autogenerated setter will set.
Using properties instead of Java-style getter/setter methods is strongly preferred in Kotlin.
(Thanks to #AlexeyRomanov for pointing out the specific rules.)
Related
I want to understand what is the difference at the deeper level between the two statements.
val myVariable: String get() = activity.myName
val myVariable: String = activity.myName
What difference does the get() makes even though I am able to access these variables from other classes and for me both works the same.
It helps to understand it better if you move your get() = to the next line.
val myVariable: String
get() = activity.myName
Because then you'll see that you can also do this:
val myVariable: String = "something"
get() = activity.myName
There are two things going on when you are defining a property.
= "something" or = activity.myName right after the property name and type is the backing field initializer. When you include this, the property is given a backing field, which is an invisible variable that can hold data for the property to use, and the expression is used to define the initial value to hold in the backing field.
Using get() creates a custom getter. This is a function that is run every time the property is accessed, and whatever the function returns is the value the property is read as. If you omit a custom getter, then it uses a default getter which simply returns the value of the backing field from point 1.
You cannot omit both the field and the custom getter, because then you would have a default getter with no backing field to retrieve, which makes no sense.
So now we can explain three possible ways of writing this property:
val myProperty: String
get() = activity.myName
// Every time you use this property, it looks up the activity property and finds the
// value of the activity's myName property. So if activity was changed to point to
// something else or myName was changed to point to something else, myProperty will
// always return the latest value when it is used.
val myProperty: String = activity.myName
// This property is initialized with the value that activity.myName holds at the time
// the class is instantiated, and it will always return this same original value even
// if activity or myName changes, because the value of the backing field is never changed.
// The value of the backing field can only be changed if you're using a var property.
val myProperty: String = activity.myName
get() = activity.myName
// This property behaves like the first one above, but it also has a useless backing
// field that is holding a reference to the original value of activity.myName. Since
// the custom getter doesn't use the backing field, the backing field can never be
// read, so it's useless.
Here's one possible use case for using both a backing field and a custom getter. If you want to keep a constant value in a backing field like in the second example above, but have some side effect like logging something each time it is accessed, you could use both. The keyword field can be used in a custom getter to access the backing field.
val myProperty: String = activity.myName
get() = field.also { Log.i(TAG, "Retrieved value of myProperty.") }
To add onto Tenfour04's answer, another way you could write your get() version is:
val myVariable: String get() {
return activity.myName
}
And that's clearly a function, right? You call it, it returns a String. When a function is simple and returns a value, you can format it as a single-expression function which looks like this:
// block function
fun something(): String {
return coolString
}
// single-expression function - you can omit the type too, if you like
fun something(): String = coolString
So the single-expression equivalent for your getter is
val myVariable: String get() = return activity.myName
The fact it's a val changes things - there are special getter and setter functions you can add to vals and vars, and you're sort of "tacking on" the function at the end of the variable declaration. Because it's a val, it's a property - you read it like a value, like println(myVariable). It's not a function, so you don't call it like println(myVariable()) or anything.
But in this case, because it has this getter function, under the hood Kotlin is calling that function whenever you read the value. And really, anything can happen in there! The value could be completely different every time. Maybe there's no value stored at all, and the getter just calls some other function to generate a value. But the code reading myVariable doesn't know or care about that - it just accesses the variable, and sees a value.
They're basically equivalent to the Java-style getter and setter functions:
fun getMyVariable(): String {
// or whatever you want to return
return activity.myName
}
fun setMyVariable(value: String) {
// do whatever with the value - store it in a variable, record it in some database, etc
}
Except you don't need to treat them as special and call a function to access them - they look and act just like a plain old variable! (And in fact, if you're calling Java setters and getters named like this, Kotlin will let you access them like properties)
So yeah, both the versions in the original question can be accessed the same way - that's the idea! But one is a basic variable - a val in fact, so it's a fixed value. The other is a getter which can do anything, including returning different values over time, calculating stuff on demand, or even just pointing at other values - maybe you want to give access to the other variable, especially if it's a var, or maybe in some versions of a class property A is identical to property B so it's easier to keep one updated and let the other just say "whatever that one says"
My goal is to create a MethodHandle that, by passing a class and a field name, reads that field with a MethodHandle getter and returns the value.
With this method I wanted to return an arbitrary object:
return new ConstantCallSite(MethodHandles.lookup().unreflectGetter(f).asType(MethodType.methodType(Object.class))).dynamicInvoker();
I received the Field f via Reflections.
The problem now is that when this method is executed, the typical error for invokeExact (WrongMethodTypeException) occurs:
WrongMethodTypeException: cannot convert MethodHandle(TestClass)String to ()Object
This also applies to ints, floats, etc.
In another thread I also already read that you can use invokeExact dynamically if the return of MethodHandle is changed to Object.
Here is a code snippet from the method, which makes use of passing a static final MethodHandle:
return (T) handle.invokeExact(testObject);
Using MethodHandle#invoke is rather out of the question for me, as I'm after performance. Without invokeExact I could possibly also fall back on using only reflections.
Does anyone know a way to do this or a workaround with similar performance? The latter plays a big role in the project. I thank those in advance who could possibly help with this problem.
A (non-static) getter needs an instance to retrieve the field's value from. You should be able to make this work by adding another Object parameter to the erased method type:
return MethodHandles.lookup().unreflectGetter(f).asType(MethodType.methodType(Object.class, Object.class));
(Also, there's no need to wrap the thing in a ConstantCallsite)
I have got my protobuf GeneratedMessage(only castable to this base) and I would like to get the text format(parsable by TextFormat class) including all fields of this message.
I see only two ways:
by reflection find all setters and put in some values, then use TextFormat
get list of fields(from api) and recreate this format
Neither of them is good, so my question is: is there any better way? If not which of these you find better?
If you have a GeneratedMessage, you may simply pass it into any of TextFormat's print methods. GeneratedMessage implements the MessageOrBuilder interface which these methods want.
EDIT: I see, your problem is that you want it to actually print all the fields, and TextFormat only prints fields that have been filled in.
You will have to fill in the fields with dummy data. This is actually pretty easy, though:
Message fillAllFields(Message prototype) {
Message.Builder builder = prototype.newBuilderForType();
for (FieldDescriptor field: builder.getDescriptorForType().getFields()) {
builder.setField(field, prototype.getField(field));
}
return builder.build();
}
The trick here is that we're calling setField() for every defined field, not just the ones that are set in prototype. For the ones that aren't set there, prototype.getField() will return the default value, but we're still explicitly setting the field to that value, so it will now show up in text format. Note that this actually creates a different message from the original -- setting a field to its default value is detectably different from leaving the field unset.
I have come across this code (simplified of course) in the project I have been assigned to.
Method Option 1
public myType getSomething(final int pTeamId) {
this.teamId = pTeamId;
final ClassABC classABC = new ClassABC(pTeamId);
...
return myType;
}
Notice how the input parameter pTeamId is being assigned to the private data member teamId in the first line of the method. Please note that there are getter and setter methods for this teamId data member (Which I have not bothered to include for simplicity's sake. Just know they are a standard getter/setter pair).
So I suppose I could write this method differently where I call the getter of the data member I just set instead of using the input parameter passed in directly as in Method Option 1:
Method Option 2
public myType getSomething(final int pTeamId) {
this.teamId = pTeamId;
final ClassABC classABC = new ClassABC(this.getTeamId());
...
return myType;
}
I realize this question may seem trivial and/or stupid to some, but I am encountering this situation frequently in a large code base I am modifying, so I am curious about which is the "correct" way to approach this, Method option 1 or Method option 2.
I came across this thread, but it targets JavaScript: speed of getter function vs direct access
My first inclination is to use Method Option 1, but I really do not have a good reason why, besides that "it looks faster...".
Can someone else provide a better reason(s)?
Specifically,
1) Is there is a proper/preferred convention/technique/practice in this scenario?
and
2) WHY is one option better than the other? Are they equal? Are there performance issues? etc.
Are there questions I am not asking? (or is this all an over-analysis)?
Any insight would be appreciated.
The getter could have logic in it like not returning null but an empty string instead.
same with the setter.
when you manipulate the variable directly you don't execute that logic.
this can also be a problem if someone overrides the getter and setter logic. (you can forbidd this by making them final) but this is not a common doing! (i would go one step further and call it an anti-pattern)
i would suggest always calling the getters/setters. and there is no real performance loss
I have an object that has a lot of attributes, each one with it's getter and setter. Each attribute has a non primitive type, that I don't know at runtime.
For example, what I have is this:
public class a{
private typeA attr1;
private typeB attr2;
public typeA getAttr1(){ return attr1; }
public typeB getAttr2(){ return attr2; }
public void setAttr1(typeA at){ attr1 = at; }
public void setAttr2(typeB at){ attr2 = at; }
}
public class typeA{
public typeA(){
// doesn't matter
}
}
public class typeB{
public typeB(){
// doesn't matter
}
}
So, using reflection, I obtained the setter method for an attribute. Setting a value in the standard way is something like this:
a test = new a();
a.setAttr1(new typeA());
But how can I do this using reflection? I already got the setAttr1() method using reflection, but I don't know how to create a new typeA object to be inserted in the setter.
Use Class#newInstance().
Class<TypeA> cls = TypeA.class;
TypeA typeA = cls.newInstance();
Or, in your specific case when you have to determine the type of the method parameter:
Class<?> cls = setterMethod.getParameterTypes()[0];
Object value = cls.newInstance();
setterMethod.invoke(bean, value);
You can learn more about reflection in Sun tutorial on the subject. That said, classnames ought to start with uppercase. I've corrected it in the above example.
By the way, instead of reinventing the Javabean reflection wheel, you may find one of the tools mentioned here useful as well.
Use getDeclaredFields() method in the Class object, to get all fields, then use field.set(classInstance, value) to set the value of field in an instance. Note: you may have to set the accessible flag on the field to true, if the field is private. No need to rely on setter methods.
I encountered this on some stuff I was doing. My general conclusion was that whenever I felt like I needed a class with a bunch of fields I was doing it wrong. Here's my thought process:
Problem:
- I need a large number of fields to hold this data
- All these fields require huge amounts of boilerplate
Solution:
use reflection to reduce the boilerplate < "you are here"
Use metadata to specify how the fields should be used
New Problems:
Reflection is difficult to understand when someone new looks at the code
Once you go meta enough to eliminate more boilerplate, the fields often have no mention in the code except through the metadata--why are they fields?
Specifying the metadata in code becomes bulky quite quickly (easiest way is a string array, by the way)
Solution: Start storing data in a collection and Specify metadata in an external data file
New problem: Errors become hard to find
Be meticulous about error checking and very explicit with your error messages. Make sure any other programmers that might use your code read the error messages. Attempt to indicate when metadata is missing or wrong and how the programmer should update the metdata--include the location of the metadata file.
Problem: No type safety
Yeah, this became somewhat annoying at times. I ended up including type information in the metadata so that if someone put the wrong value in a field, it could be detected--essentially this moves type safety from build time to run time which was fine in my case.
Problem: The metadata is needed repeatedly throughout the life of the object
Rather than looking it up by name every time it's used, I'd parse the metadata at the beginning and put it in an object (call it an IntHolder). This holder would end up in the hashtable and it would contain the current value as well as a reference to the parsed metadata.
Example
Here's what my metadata would end up for one field of a style sheet:
FieldName: Age
FieldType Integer
ScreenBinding: AgeTextField
DBBinding: User.age
Validation: IntRange(0, 120); "Age is out of range"
The field name might be how it is displayed to the user or just for use in your program. In general, you shouldn't need to directly manipulate this type of data by name--but of course you do sometimes.
When you do need to use, use getInt("Age") and setInt("Age", 12) instead of getAge() and setAge(12)--slightly more verbose but not really a problem.
If it is a problem, you can make getAge/setAge helper methods and you never need to know it's not a field, but that does start piling on the boilerplate again.
FieldType: specifies how it's stored and lets you implement type checking.
ScreenBinding and DBBinding are used to copy the value into and out of other systems. I also used this type of mechanism to transfer the data from server to client and back.
The fun one is Validation. When pulling data off the screen it can be passed to a validator in a very progmatic way. The same validator can be used before committing to the DB.
Validators can do a lot more than that, they can act as triggers (if a value changes, do this) or actions (when user submits a screen, do this). These are a simple objects with the ability to take a value (through an interface)--they can be as flexible or powerful as you like but are not tied directly to any object except through the meta-data.
The only problem with this approach is you have to be the type of programmer that enjoys writing fixtures instead of error-prone boilerplate. (Yes, I find that the amount of time is about equal, but I tend to get really slow when I have to implement boilerplate)
After doing this a few times I really love the pattern, but it gets difficult to implement. Next time I do it I'm going to try to make it into a library of some type.
If you want to set a "fresh" object in each setter of your class, you can typically do it by getting the Method, for each Method you get the Class of the arguments with getParameterTypes() , for each Class you invoke Class.newInstance() ... and cross your fingers (that should break with primitive types -I doubt Java does autoboxing here).
You can always ask if a parameter is a pimitive calling isPrimitive()
Why would you want to set "empty" instances for primitive fields of a class? They are already initialized. Do you want to "reset" them ?