I've been reading up on encapsulation and was wondering; if I make a new class, is it by default mutable?
If so, how would I go about making it an immutable class, if possible, without just doing defensive copying?
Thanks.
It depends on what you put in the class.
public class MutableClass {
private String firstName;
public MutableClass(String s) {
firstName = s;
}
public String getFirstName() {
return firstName;
}
// this allows mutation...
public void setFirstName(String s) {
firstName = s;
}
}
public class ImmutableClass {
private String firstName;
public MutableClass(String s) {
firstName = s;
}
public String getFirstName() {
return firstName;
}
}
That doesn't account of things like setAccessible with reflection, but I expect that is not what you are concerned about.
I hope that helps.
Related
I am using Springboot 2.1.2.RELEASE. I have a get request with an object as input parameter. Expecting the attributes in my class to be request parameters. My EmployeeBean has properties in java naming convention. But I need the custom names to request parameters. Tried to achieve that using #JsonProperty/ #Jsongetter/ #JsonSetter annotations but its not working. Am I missing something?
#RequestMapping(value="/api", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE )
public List<Map<String, Object>> getEmployeeData(EmployeeBean employeeBean
#Data
public class EmployeeBean implements Serializable {
private static final long serialVersionUID = -2757478480787308113L;
#JsonProperty(value="first_name")
private String firstName;
#JsonProperty(value="last_name")
private String lastName;
Try this,
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#JsonProperty(value="first_name")
public void setFirst_name(String firstName) {
this.firstName = firstName;
}
#JsonProperty(value="last_name")
public void setLast_name(String lastName) {
this.lastName = lastName;
}
controller
#RestController
public class JsonController {
#RequestMapping(value="/api", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE )
public List<Map<String, Object>> getEmployeeData(EmployeeBean employeeBean) {
System.out.println("employeeBean: "+employeeBean);
return null;
}
}
result:
employeeBean: EmployeeBean [firstName=firstName10, lastName=lastName20]
I've tested and it's worked
other options, using JsonCreator in constructor:
private String firstName;
private String lastName;
#JsonCreator
public EmployeeBean(#JsonProperty("first_name") String first_name, #JsonProperty("last_name") String last_name) {
this.firstName = first_name;
this.lastName = last_name;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
I have written a wcf program where I have an class library where I declared the function which contains a class as a parameter.
I accessed that function in a client program but I don't know how to pass the class to that function. I will write the code below.
I have an interface which contains basic function declaration
In the class library there is another class it is implementing the interface. That interface contains a method which takes a class as parameter.
That class which is parameter contains properties.
[ServiceContract]
public interface ICarDetails
{
[OperationContract]
string updateCarDetails(Car c);
}
public class CarDetails : ICarDetails
{
public string updateCarDetails(Car c)
{
//some operations and initilizations
string example = Car.carno = "1234";
return "success";
}
}
Public class Car
{
private string carno;
private string carModel;
public string CARNO
{
get{ return carno; }
set{ carno = value; }
}
public string CARMODEL
{
get{ return carModel; }
set{ carModel = value; }
}
}
3) I will get access this function in myclient program where I consume. While consuming I need to send a class right? If so how can I send a class.
class Program
{
static void Main(string[] args)
{
CarDetailsserviceClient client = new CarDetailsserviceClient();
string abc = client.updateCarDetails(); // This shows error
}
}
public class carclient
{
public string carno = "6789";
}
I want to send this client class carclient to wcf service function updatecardetails.
You need to mark your Car type with the DataContract and DataMember attributes before you can pass it across the service boundary:
[DataContract]
public class Car
{
private string carno;
private string carModel;
[DataMember]
public string CARNO
{
get{ return carno; }
set{ carno = value; }
}
[DataMember]
public string CARMODEL
{
get{ return carModel; }
set{ carModel = value; }
}
}
If you do this then regenerate your service client, you will find you have access to the Car type from you calling code and you won't need to define your own type on the client side.
You can't pass a class, you must pass an object of that class. Create new object :
Car carclient = new Car() { CARNO = "6789" };
Then, pass it in argument :
string abc = client.updateCarDetails(carclient);
Car must be include in the DataContract like this :
[DataContract]
public class Car
{
private String carno;
private String carModel;
[DataMember]
public String CARNO
{
get { return this.carno; }
set { this.carno = value; }
}
[DataMember]
public String CARMODEL
{
get { return this.carModel; }
set { this.carModel = value; }
}
}
I have the following objects:
#JsonFilter("myFilter")
public class Person {
private Name name;
private int age;
public Name getName() {return name;}
public void setName(Name name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
#JsonFilter("myFilter")
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
}
I wrote a method to marshall a Person object like this:
#Test
public void test() throws Exception {
Person person = new Person();
person.setAge(10);
Name name = new Name();
name.setFirstName("fname");
name.setLastName("lastname");
person.setName(name);
ObjectMapper mapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name.firstName"));
System.out.println(mapper.filteredWriter(filters).writeValueAsString(person));
}
What I'd like to see is JSON like this:
{"name":{"firstName":"fname"}}
Is something like that possible?
Ok, figured it out. Varargs would have made this a bit prettier, but oh well. Just hope I don't have two inner beans which have properties with the same name. I wouldn't be able to make the distinction between the two
FilterProvider filters = new SimpleFilterProvider()
.addFilter("myFilter", SimpleBeanPropertyFilter
.filterOutAllExcept(new HashSet<String>(Arrays
.asList(new String[] { "name", "firstName" }))));
There's a better way that solves problem with property name conflicts. Just add another filter to class Name ("nameFilter"):
#JsonFilter("personFilter")
public class Person {
private Name name;
private int age;
public Name getName() {return name;}
public void setName(Name name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
#JsonFilter("nameFilter")
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
}
And then add 2 filters, one for Person and one for Name:
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("personFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name"))
.addFilter("nameFilter", SimpleBeanPropertyFilter.filterOutAllExcept("firstName"));
I have an entity declared similar to this:
public class Comment
{
public Comment(string text, DateTime creationDate, string authorEmail)
{
Text = text;
CreationDate = creationDate;
AuthorEmail = authorEmail;
}
public virtual string Text { get; private set; }
public virtual DateTime CreationDate { get; set; }
public virtual string AuthorEmail { get; private set; }
}
I have taken it from Is it OK to call virtual properties from the constructor of a NHibernate entity?
I get warning as 'Virtual Calls in constructor'.
Though, it doesn't pose any practical issue because virtual members are declared solely for NH to proxy. However, I was wondering if I should move the constructor method to a new factory class with new method being declared as
CreateComment(string text, DateTime creationDate, string authorEmail)
What will be the best practice in this case?
Please note that currently I have 4-5 overloaded constructors in my domain entity. Above is just an example.
Thank you!
I have tested with FluentNHibernate, you can do it like this:
public class Comment
{
private string _text;
private DateTime _creationDate;
private string _authorEmail;
public Comment(string text, DateTime creationDate, string authorEmail)
{
_text = text;
_creationDate = creationDate;
_authorEmail = authorEmail;
}
public virtual string Text
{
get { return _text; }
private set { _text = value; }
}
public virtual DateTime CreationDate
{
get { return _creationDate; }
set { _creationDate = value; }
}
public virtual string AuthorEmail
{
get { return _authorEmail; }
private set { _authorEmail = value; }
}
}
I prefer having a parameterless (default) constructor and constructing like so:
var comment = new Comment {
Text = "Something offensive and political.",
CreationDate = DateTime.Now,
AuthorEmail = "someonestupidwithanopinion17#aol.com"
};
Now the issue doesn't matter.
If your properties are only virtual to accomodate nHibernate, you can just make them encapsulate concrete fields (nhibernate knows how to cope with that: see here (default-access) and here (access).
it's supported in fluent nh as well.
I have question connected with interfaces and abstract classes.
I'll give to you simple example, that could explain what I want to do. So, Lets start.
public interface A
{
string param1 { set; get;}
string param1 { set; get;}
A CreateObject(string p1,string p2);
}
public class MyClass1 : A
{
public string param1 { set; get; }
public string param2 { set; get; }
public A CreateObject(string p1,string p2)
{
var obj = new MyClass1();
obj.param1 = p1;
obj.param2 = p2;
return obj;
}
}
public class MyClass2 : A
{
public string param1 { set; get; }
public string param2 { set; get; }
public A CreateObject(string p1,string p2)
{
var obj = new MyClass2();
obj.param1 = p1;
obj.param2 = p2;
return obj;
}
}
// I have little problem with this function
public List<A> GetNodes(int count)
{
var lst_Objects = new List<a>();
for(int i=0; i<count; i++)
{
string Param1 = GetParam1();
string Param2 = GetParam2();
lst_Objects.Add(new A.CreateObject(Param1,Param2); // but it defenitly doesn't work(wrong way)
}
return lst_Objects;
}
I have problems with GetNodes function.
Tip:
MyClass1 and MyClass2 is Entity objects, and because of this reason I can not create abstract class, and use some generic to resolve this problem.
I will grateful for your ideas
You didn't mention A.CreateObject as static while other concrete class MyClass1 / MyClass2 are left as static. Use
lst_Objects.Add(MyClass1.CreateObject(Param1,Param2);
or
lst_Objects.Add(MyClass2.CreateObject(Param1,Param2);
instead.
Also to mention, you need to make sure you define A.CreateObject in both of the classes, otherwise you need to make both of them abstract which is not what you want. Rather remove the nonstatic method CreateObject from interface A.
Your interface declares a CreateObject method, which neither of your classes implement. Your classes implement a static CreateObject, which does not satisify the interface. Interfaces cannot declare static members.
I have bad solution. I'll create class like this:
public class Universal: A
{
public string param1 { set; get; }
public string param2 { set; get; }
public static A CreateObject(string p1,string p2)
{
var obj = new MyClass1();
obj.param1 = p1;
obj.param2 = p2;
return obj;
}
Function GetNodes will have appearance like this:
public List<A> GetNodes(int count)
{
var lst_Objects = new List<a>();
for(int i=0; i<count; i++)
{
string Param1 = GetParam1();
string Param2 = GetParam2();
lst_Objects.Add(Universal.CreateObject(Param1 ,Param2));
}
return lst_Objects;
}
This function will return List of objects which have type A(which I easily convert into myclass1 or myclass2 object.
Is it good Idea?
Thank for your attention.