Understanding the syntax of Getters/Setters in Kotlin - kotlin

Regarding a code example like this one:
var someProperty: String = "defaultValue"
get() = field
set(value) { field = value }
Is it mandatory to write the get-/set-methods right below the attribute-declaration? It won't work if I have something in between attribute-declaration and get/set-definition?
Is the nesting just for better reading or is it part of the syntax?

because you're using var and its public all this part
get() = field
set(value) { field = value }
is redundant and the Kotlin compiler should alert about it.
also, you can see that when you compile your code to kotlin byte code with or without the setter and getter
the outcome is the same
#Metadata(
mv = {1, 4, 1},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0005\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002R\u001a\u0010\u0003\u001a\u00020\u0004X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u0005\u0010\u0006\"\u0004\b\u0007\u0010\b¨\u0006\t"},
d2 = {"Lorg/example/Fo;", "", "()V", "someProperty", "", "getSomeProperty", "()Ljava/lang/String;", "setSomeProperty", "(Ljava/lang/String;)V", "stream"}
)
public final class Fo {
#NotNull
private String someProperty = "defaultValue";
#NotNull
public final String getSomeProperty() {
return this.someProperty;
}
public final void setSomeProperty(#NotNull String var1) {
Intrinsics.checkNotNullParameter(var1, "<set-?>");
this.someProperty = var1;
}
}
and last for the order question, The full syntax for declaring a property is
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
so you cant add anything in between the declaration parts

Related

HTTP end point property string starts with "is" will get omit [duplicate]

This might be a duplicate. But I cannot find a solution to my Problem.
I have a class
public class MyResponse implements Serializable {
private boolean isSuccess;
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Getters and setters are generated by Eclipse.
In another class, I set the value to true, and write it as a JSON string.
System.out.println(new ObjectMapper().writeValueAsString(myResponse));
In JSON, the key is coming as {"success": true}.
I want the key as isSuccess itself. Is Jackson using the setter method while serializing? How do I make the key the field name itself?
This is a slightly late answer, but may be useful for anyone else coming to this page.
A simple solution to changing the name that Jackson will use for when serializing to JSON is to use the #JsonProperty annotation, so your example would become:
public class MyResponse implements Serializable {
private boolean isSuccess;
#JsonProperty(value="isSuccess")
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
This would then be serialised to JSON as {"isSuccess":true}, but has the advantage of not having to modify your getter method name.
Note that in this case you could also write the annotation as #JsonProperty("isSuccess") as it only has the single value element
I recently ran into this issue and this is what I found. Jackson will inspect any class that you pass to it for getters and setters, and use those methods for serialization and deserialization. What follows "get", "is" and "set" in those methods will be used as the key for the JSON field ("isValid" for getIsValid and setIsValid).
public class JacksonExample {
private boolean isValid = false;
public boolean getIsValid() {
return isValid;
}
public void setIsValid(boolean isValid) {
this.isValid = isValid;
}
}
Similarly "isSuccess" will become "success", unless renamed to "isIsSuccess" or "getIsSuccess"
Read more here: http://www.citrine.io/blog/2015/5/20/jackson-json-processor
Using both annotations below, forces the output JSON to include is_xxx:
#get:JsonProperty("is_something")
#param:JsonProperty("is_something")
When you are using Kotlin and data classes:
data class Dto(
#get:JsonProperty("isSuccess") val isSuccess: Boolean
)
You might need to add #param:JsonProperty("isSuccess") if you are going to deserialize JSON as well.
EDIT: If you are using swagger-annotations to generate documentation, the property will be marked as readOnly when using #get:JsonProperty. In order to solve this, you can do:
#JsonAutoDetect(isGetterVisibility = JsonAutoDetect.Visibility.NONE)
data class Dto(
#field:JsonProperty(value = "isSuccess") val isSuccess: Boolean
)
You can configure your ObjectMapper as follows:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
&& method.getName().startsWith("is")) {
return method.getName();
}
return super.nameForGetterMethod(config, method, defaultName);
}
});
I didn't want to mess with some custom naming strategies, nor re-creating some accessors.
The less code, the happier I am.
This did the trick for us :
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates
public class MyResponse {
private String id;
private #JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name
private #JsonProperty("isDeleted") boolean isDeleted;
}
Building upon Utkarsh's answer..
Getter names minus get/is is used as the JSON name.
public class Example{
private String radcliffe;
public getHarryPotter(){
return radcliffe;
}
}
is stored as { "harryPotter" : "whateverYouGaveHere" }
For Deserialization, Jackson checks against both the setter and the field name.
For the Json String { "word1" : "example" }, both the below are valid.
public class Example{
private String word1;
public setword2( String pqr){
this.word1 = pqr;
}
}
public class Example2{
private String word2;
public setWord1(String pqr){
this.word2 = pqr ;
}
}
A more interesting question is which order Jackson considers for deserialization. If i try to deserialize { "word1" : "myName" } with
public class Example3{
private String word1;
private String word2;
public setWord1( String parameter){
this.word2 = parameter ;
}
}
I did not test the above case, but it would be interesting to see the values of word1 & word2 ...
Note: I used drastically different names to emphasize which fields are required to be same.
You can change primitive boolean to java.lang.Boolean (+ use #JsonPropery)
#JsonProperty("isA")
private Boolean isA = false;
public Boolean getA() {
return this.isA;
}
public void setA(Boolean a) {
this.isA = a;
}
Worked excellent for me.
If you are interested in handling 3rd party classes not under your control (like #edmundpie mentioned in a comment) then you add Mixin classes to your ObjectMapper where the property/field names should match the ones from your 3rd party class:
public class MyStack32270422 {
public static void main(String[] args) {
ObjectMapper om3rdParty = new ObjectMapper();
om3rdParty .addMixIn(My3rdPartyResponse.class, MixinMyResponse.class);
// add further mixins if required
String jsonString = om3rdParty.writeValueAsString(new My3rdPartyResponse());
System.out.println(jsonString);
}
}
class MixinMyResponse {
// add all jackson annotations here you want to be used when handling My3rdPartyResponse classes
#JsonProperty("isSuccess")
private boolean isSuccess;
}
class My3rdPartyResponse{
private boolean isSuccess = true;
// getter and setter here if desired
}
Basically you add all your Jackson annotations to your Mixin classes as if you would own the class. In my opinion quite a nice solution as you don't have to mess around with checking method names starting with "is.." and so on.
there is another method for this problem.
just define a new sub-class extends PropertyNamingStrategy and pass it to ObjectMapper instance.
here is a code snippet may be help more:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
String input = defaultName;
if(method.getName().startsWith("is")){
input = method.getName();
}
//copy from LowerCaseWithUnderscoresStrategy
if (input == null) return input; // garbage in, garbage out
int length = input.length();
StringBuilder result = new StringBuilder(length * 2);
int resultLength = 0;
boolean wasPrevTranslated = false;
for (int i = 0; i < length; i++)
{
char c = input.charAt(i);
if (i > 0 || c != '_') // skip first starting underscore
{
if (Character.isUpperCase(c))
{
if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_')
{
result.append('_');
resultLength++;
}
c = Character.toLowerCase(c);
wasPrevTranslated = true;
}
else
{
wasPrevTranslated = false;
}
result.append(c);
resultLength++;
}
}
return resultLength > 0 ? result.toString() : input;
}
});
The accepted answer won't work for my case.
In my case, the class is not owned by me. The problematic class comes from 3rd party dependencies, so I can't just add #JsonProperty annotation in it.
To solve it, inspired by #burak answer above, I created a custom PropertyNamingStrategy as follow:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
if (method.getParameterCount() == 1 &&
(method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) &&
method.getName().startsWith("set")) {
Class<?> containingClass = method.getDeclaringClass();
String potentialFieldName = "is" + method.getName().substring(3);
try {
containingClass.getDeclaredField(potentialFieldName);
return potentialFieldName;
} catch (NoSuchFieldException e) {
// do nothing and fall through
}
}
return super.nameForSetterMethod(config, method, defaultName);
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
&& method.getName().startsWith("is")) {
Class<?> containingClass = method.getDeclaringClass();
String potentialFieldName = method.getName();
try {
containingClass.getDeclaredField(potentialFieldName);
return potentialFieldName;
} catch (NoSuchFieldException e) {
// do nothing and fall through
}
}
return super.nameForGetterMethod(config, method, defaultName);
}
});
Basically what this does is, before serializing and deserializing, it checks in the target/source class which property name is present in the class, whether it is isEnabled or enabled property.
Based on that, the mapper will serialize and deserialize to the property name that is exist.

How to generate data class from class instance

I've got some configuration values in a JSON file which I want to parse via gson to a data-class. I want to generate a new class, based on the created data-class where the values are final.
This all should happen during my CI-Pipeline and the generated class should then be used when my application is running.
Simple example to clarify:
I've got this data class
data class MyDataClass(val name:String, val age:Int)
and via parsing (gson) a instance like this is created
MyDataClass("john", 42)
Is there a way to create a (data) class based on the new instance of MyDataClass so anything like this will be created?
class MyDataClassFinal{
val name = "john"
val age = 42
}
Use .copy() and modify only the parameters you need to. For example:
val joe = MyDataClass(“Joe”, 42)
val mary = joe.copy(name = “Mary”) // age is 42
I've got some configuration values in a json file wich I want to parse via gson to a data-class. I want to generate a new class, based on the created data-class where the values are final.
There is nothing for you to do here. The data class, as you've described it, is final. It is not open so the class is final and the fields are vals and only set via constructor, so they can't be changed, so they too are final.
You can see the Java equivalent of the class by going to doing a search for "Actions", looking for Kotlin Bytecode, then hit Decompile to see the Java source. It looks like this:
#Metadata(
mv = {1, 1, 18},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000 \n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0002\b\t\n\u0002\u0010\u000b\n\u0002\b\u0004\b\u0086\b\u0018\u00002\u00020\u0001B\u0015\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005¢\u0006\u0002\u0010\u0006J\t\u0010\u000b\u001a\u00020\u0003HÆ\u0003J\t\u0010\f\u001a\u00020\u0005HÆ\u0003J\u001d\u0010\r\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u0005HÆ\u0001J\u0013\u0010\u000e\u001a\u00020\u000f2\b\u0010\u0010\u001a\u0004\u0018\u00010\u0001HÖ\u0003J\t\u0010\u0011\u001a\u00020\u0005HÖ\u0001J\t\u0010\u0012\u001a\u00020\u0003HÖ\u0001R\u0011\u0010\u0004\u001a\u00020\u0005¢\u0006\b\n\u0000\u001a\u0004\b\u0007\u0010\bR\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\t\u0010\n¨\u0006\u0013"},
d2 = {"Lcore/lib/extensions/MyDataClass;", "", "name", "", "age", "", "(Ljava/lang/String;I)V", "getAge", "()I", "getName", "()Ljava/lang/String;", "component1", "component2", "copy", "equals", "", "other", "hashCode", "toString", "treking-android.dominicore-android"}
)
public final class MyDataClass {
#NotNull
private final String name;
private final int age;
#NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public MyDataClass(#NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.age = age;
}
#NotNull
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
}
#NotNull
public final MyDataClass copy(#NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
return new MyDataClass(name, age);
}
// $FF: synthetic method
public static MyDataClass copy$default(MyDataClass var0, String var1, int var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = var0.name;
}
if ((var3 & 2) != 0) {
var2 = var0.age;
}
return var0.copy(var1, var2);
}
#NotNull
public String toString() {
return "MyDataClass(name=" + this.name + ", age=" + this.age + ")";
}
public int hashCode() {
String var10000 = this.name;
return (var10000 != null ? var10000.hashCode() : 0) * 31 + this.age;
}
public boolean equals(#Nullable Object var1) {
if (this != var1) {
if (var1 instanceof MyDataClass) {
MyDataClass var2 = (MyDataClass)var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age) {
return true;
}
}
return false;
} else {
return true;
}
}
}
As you can see, the class, it's fields, and their accessors are all final.

MockMvc POST returning 400 - expecting 201

I'm trying to write a controller unit test for a #PostMapping but am getting a failed test
Status expected:<201> but was:<400>
The controller works as expected in Postman so I know it actually works, but it would be nice to have a working unit test as well.
What am I doing wrong?
TEST
#Test
#DisplayName("CREATE NEW ENFORCEMENT ACTION")
void testCreateNewEnforcementAction() throws Exception {
EnforcementAction mockAction = new EnforcementAction();
mockAction.setSystemId(1289);
mockAction.setCurrentStaff("ralbritton");
mockAction.setCurrentStatus("NEEDED");
mockAction.setCreatedOn(LocalDateTime.now());
mockAction.setCreatedBy("ralbritton");
mockAction.setEaType("IF");
mockAction.setEaCode("CAP");
mockAction.setDeleted(false);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(mockAction);
mockMvc.perform(MockMvcRequestBuilders.post("/api/enforcementactions/action")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
.characterEncoding("utf-8"))
.andExpect(status().isCreated()); //Have also tried this as .isOK() (didn't make a diff)
//.andReturn(); ///Added and removed this line to see if it made a differnce (it did not)
}
CONTROLLER BEING TESTED
#PostMapping("/api/enforcementactions/action")
public ResponseEntity<?> createNewEnforcementAction(#RequestBody EnforcementAction newAction) {
service.createEnforcementAction(newAction);
return new ResponseEntity<>(newAction, HttpStatus.CREATED);
}
MODEL
UPDATE: I'm adding in the model to show that there is not Bean Validation on fields
public class EnforcementAction {
private Integer eaId;
private Integer systemId;
private String alternateNumber;
private String systemName;
private Integer tenschdId;
private String currentStaff;
private String currentStatus;
private LocalDate dateActionIssued;
private LocalDate dateActionClosed;
private boolean deleted;
private LocalDateTime createdOn;
private String createdBy;
private LocalDateTime modifiedOn;
private String lastModifiedBy;
private String eaType;
private String eaCode;
private String comment;
private Long daysSinceCreate;
private List<EaStaffHistory> staffAssigned = new ArrayList<>();
private List<EaDocStatusHistory> documentStatus = new ArrayList<>();
private List<EaComments> eaComments = new ArrayList<>();
/** Constructors */
public EnforcementAction() {
}
public EnforcementAction(Integer eaId, Integer systemId, String systemName, Integer tenschdId,
String currentStaff, String currentStatus, Long daysSinceCreate,
String createdBy, String lastModifiedBy, LocalDate dateActionIssued, LocalDate dateActionClosed,
String eaType, String eaCode, LocalDateTime createdOn) {
this.eaId = eaId;
this.systemId = systemId;
this.tenschdId = tenschdId;
this.systemName = systemName;
this.currentStaff = currentStaff;
this.currentStatus = currentStatus;
this.createdBy = createdBy;
this.lastModifiedBy = lastModifiedBy;
this.dateActionClosed = dateActionClosed;
this.dateActionIssued = dateActionIssued;
this.eaType = eaType;
this.eaCode = eaCode;
this.daysSinceCreate = daysSinceCreate;
this.createdOn = createdOn;
}
...getters and setters....
POSTMAN showing successful post:
EDIT: I've updated the OP code to reflect current state. Still having the same issue though.
The reason for the 400 is how you send your payload to your controller. You are not serializing the Java object to JSON, but use the .toString() representation of it:
.content(String.valueOf(mockAction)))
Either make use of the ObjectMapper or prepare a custom JSON string:
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(mockAction);
mockMvc.perform(MockMvcRequestBuilders
.post("/api/enforcementactions/action")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isCreated());
OK so I finally figured out my problem and I'm posting it here in case someone else has the same issue. While #Rieckpil was correct in all his suggestions (and I will mark his answer as correct) the other problem I was having was in my mockAction object. I had:
mockAction.setCreatedOn(LocalDateTime.now())
Even though createdOn is of type LocalDateTime it was getting deconstructed in the body to look like this:
"createdOn": {
"dayOfWeek": "WEDNESDAY",
"dayOfYear": 204,
"month": "JULY",
"year": 2020,
"dayOfMonth": 22,
"hour": 12,
"minute": 43,
"monthValue": 7,
"nano": 839000000,
"second": 10,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}
When I passed this as the createdOn variable into Postman I was able to get a meaningful error .HttpMessageNotReadableException: JSON parse error: Expected array or string.; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Expected array or string. at [Source: (PushbackInputStream); line: 12, column: 21] (through reference chain: gov.deq.utah.enforcementactions.models.enforcementActions.EnforcementAction["createdOn"])
The test passed when I removed this. I kept all other suggestions provided.

Put "List of Objects" in KrollDict with Titanium Android Module Development

I have a custom class declared in the module source code.
public class Friend{
public String name;
public List<String> phoneNumbers;
public List<String> emailAddresses;
public Friend(String name, List<String>emailAddresses,
List<String>phoneNumbers){
this.name = name;
this.emailAddresses = emailAddresses;
this.phoneNumbers = phoneNumbers;
}
}
I declared an Android Method in the Module
#Kroll.method
protected synchronized void getListOfObjects(){
List<String> emailAddresses = Arrays.asList("email1#yahoo.com", "email2#yahoo.com", "email3#yahoo.com");
List<String> phoneNumbers = Arrays.asList("1", "2", "3");
List<Friend> friendList = new ArrayList<Friend>();
friendList.add(new Friend("test1", emailAddresses, phoneNumbers));
friendList.add(new Friend("test2", emailAddresses, phoneNumbers));
friendList.add(new Friend("test3", emailAddresses, phoneNumbers));
KrollDict kd = new KrollDict();
kd.put("friendList", friendList);
if (hasListeners("onShow")) {
fireEvent("onShow", kd);
}
}
Upon Calling the getListOfOjects method in the Titanium App
module.getListOfObjects();
module.addEventListener('onShow', function(e){
Ti.API.info(JSON.stringify(e.friendList));
});
I cant seem to retrieve the friendList object.
The EXPECTED RESULT that I wanted to achieve would be like this
[
{test1, ["email1#yahoo.com", "email2#yahoo.com", "email3#yahoo.com"], ["1", "2", "3"]},
{test2, ["email1#yahoo.com", "email2#yahoo.com", "email3#yahoo.com"], ["1", "2", "3"]},
{test3, ["email1#yahoo.com", "email2#yahoo.com", "email3#yahoo.com"], ["1", "2", "3"]}
]
The question is, HOW TO ACHIEVE THE EXPECTED RESULT BASED ON THE SAMPLE CODES ABOVE?
Convert the List object into JSON string using GSON and assign the result string to the KrollDict property
KrollDict kd = new KrollDict();
Gson gson = new Gson();
String friendListStr = gson.toJson(friendList);
kd.put("friendList", friendListStr);
Another option is to return an object array like this:
KrollDict kd = new KrollDict();
Object[] obj = new Object[friendList.size()];
for (int i=0; i< friendList.size(); ++i){
KrollDict model = new KrollDict();
model.put("name", friendList.get(i).name);
// ...
obj[i] = model;
}
kd.put("list", obj);
fireEvent("onShow", kd);
That way you'll have an array in your event and don't need to convert that string into json later on.
If you want to use a JSON you can use TiConvert with toJSON, toJSONArray or toJSONString depending on your parameter. No need for Gson.

Rhino Mocks changing the body of method during unit test c#

So the problem is as follows. I am unit testing a class SampleClass using Rhino Mocks 3.6. For the tests I use a mock of InnerClass as it is used in the SampleClass constructor. InnerClass has a method called TheMethod(ref string s1,ref string s2). Here is where the problem begins. TheMethod(ref string,ref string) is doing nothing with the parameters and I want TheMethod to actually modify one of the strings (s1). Is it possible, using Rhino Mocks, to do such thing? If so, then how? WhenCalled? Do() handler? I'm clueless. Here's the pseudocode
Class SampleClass
{
Public String SampleClassMethod()
{
string s1 = string.Empty;
string s2 = string.Empty;
string s_final = this.InnerClass.TheMethod(ref s1, ref s2); //TheMethod() which is doing
//nothing with the given strings
if (s_final == "something")
return s1;
}
}
The result is, that s1 is unchanged and for the testing reasons I would like the TestMethod() to modify s1's value WITHOUT changing the body of TheMethod() itself
[TestMethod]
public void TestMethod1()
{
//generating mocks
//SampleClass target; //tested class object
Expect.Call(InnerClassMock.TheMethod(
ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Equal(s1), string1).Dummy,
ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Equal(s1), string1).Dummy)).IgnoreArguments();
string temp = target.SampleClassMethod();
Assert.AreEqual("1234", temp);
}
Assuming your inner class looks something like this (Note that TheMethod is virtual):
public class SomeClass
{
public virtual string TheMethod(ref string s1, ref string s2)
{
s1 = "X";
s2 = "Y";
return "Z";
}
}
You can use Rhino.Mock's "OutRef" option to define output for ref arguments:
var mock = MockRepository.GenerateStub<SomeClass>();
string temp1 = "", temp2 = "";
mock.Stub(m => m.TheMethod(ref temp1, ref temp2)).OutRef("AAA", "BBB").Return("DEF");
var my1 = "";
var my2 = "";
var result = mock.TheMethod(ref my1, ref my2);
After running this code, my1 will be "AAA", my2 will be "BBB" and result will be "DEF".