• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Passing objects by value instead of by reference (Java 16.0.1)

 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Cone wrote:I had fun doing the "Barking Dog" exercise with a single if statement.  If we were allowed to do it using the ternary operator (which we haven't learned yet) the solution could be done in a single statement:


Ok, so here's where I would course correct you: prefer Clear code over Clever code. If you're going to put everything in one line, please learn Perl. Don't do that in Java.

You'll do yourself and others a huge favor if you write this kind of code instead:

A guy named John Woods once wrote "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” Keep that in mind when you start writing code that others may have to read or maintain.
 
Ranch Hand
Posts: 91
3
Eclipse IDE MySQL Database Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What I mean by reference ID:  In the code as is now, I have an object roomy and an object exRoomy.  From those object names I can keep a clear mental reference to which object refers to the object when he lived here and which object refers to when he went to fire-school.  If I moved to the model, that easy reference disappears.  While I have the code.... [scrolls back to look lup the spelling of the word] immutable, if I accidentally try and assign a new person to "exRoomy" Java will sound the buzzer.  So as the code is now, 1. I have meaningful names (to me) for my objects, and 2. I can't accidentally reuse an object name.  Both of those seem like features not bugs, particularly when I start writing larger programs. So even though adding new user objects (which I don't see happening in real life, but is serving as an example) is currently a two step process the advantages of doing it that way seems to out-weigh the disadvantages.  I do look forward to learning about these HashSets Paul (or you or maybe both) talked about.  For now, I'm trudging on through the course sequentially and doing all the code exercises, even if they are easy.  If nothing else, the repetition is helping me have less buggy code because "the Java way/syntax" is becoming a habit.

Campbell Richie wrote:This (old style guide link) is what you should write:-

 Yes between my last msg and reading yours I figured out that most boolean methods can just be the word return followed by boolean math.  I wrote some beauties last night or the night before.... both I guess.  My favorite was the leap year problem.  Mostly because it made me think.... I cut down my code several times...  I'd be working on a completely different problem and something about writing  the current solution would prompt me to realize I had redundant checks in my previous code.  I'm enjoying the course so far.  I did send in a query to the teacher  to see if it's OK to use things we haven't  officially been taught in our solutions (like the ternary operator, which is still a valid construct for non-boolean methods that return strings.)  

Thank you all for being awesome and have a way-cool rest of your weekend!
Peace out,
~d
 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Cone wrote:. . .  While I have the code. . . . immutable, if I accidentally try and assign a new person to "exRoomy" Java will sound the buzzer. . . .

You don't need to be fully immutable to prevent reassignments of variables. You simply have to mark the declaration with the keyword final. The compiler will complain bitterly if you assign that variable any number of times except once.

1. I have meaningful names . . .

Quite right Make all variable names, except those with a very short scope, clear to anybody reading the code (at least if they speak the same language as you).

2. I can't accidentally reuse an object name. . . .

The object itself hasn't got a name; it is the reference that has a name, the name of its variable. Yes, it is a feature that you can't have two variables of the same type in scope simultaneously. (But you can have a field and a local variable with the same name.)

I do look forward to learning about these HashSets Paul (or you or maybe both) talked about. . . .

Both. Careful; you would have to learn the whole of the collections framework (well, the commonly used classes anyway), and that is a big task. Java™ Tutorials section.

the word return followed by boolean math. . . . the leap year problem. . . .
Thank you all . . . Peace . . .

Thank you.
When you simply return an expression, your code can become so much simpler and clearer to read. Just beware of making the expressions so complicated that the legibility goes out of the window See (?)Junilu's example dividing the barking dog into two parts.
 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another way to pass a mutable object around but protect it from being mutated is to have it implement an immutable interface that only has methods that don't mutate the object (e.g., has only getter methods). Then you pass the mutable object, in the guise of that immutable interface, to methods. They won't be able to mutate the object (unless they cheat).
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Clever idea. Does that mean the receiving method has to declare its parameters as the immutable interface? No, you can return it as the immutable type. The getXXX() methods would have to return defensive copies if they return mutable reference types.
But what do you think of this suggestion? If somebody has defined a class as mutable, we should always treat it as mutable.
 
David Cone
Ranch Hand
Posts: 91
3
Eclipse IDE MySQL Database Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:...
You'll do yourself and others a huge favor if you write this kind of code instead:

A guy named John Woods once wrote "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” Keep that in mind when you start writing code that others may have to read or maintain.



I understand and will do as you say.  One thing that greatly frustrates me about the Udemy.com Java training course is that you can only use as many methods as they request.  Another thing that... concerns me is I wonder if working for NASA contractors when I was young and my first college programming teacher (who taught me beginning Visual Basic) got me in a mindset of using the least CPU cycles vs using the simplest code.  I read some of the solutions other people have submitted and I have no idea how their mind is thinking to come up with the short solutions that they do.

For example, one homework problem was to find the largest prime factor of a number.  Now it's been way to long ago for me to remember who taught me this, but I know if you want to factor a number, you don't have to test all the way from 2 to the number you can test up to the square root of the number and for every factor i, you will also have a factor number/i. (Less CPU cycles)  It further goes to reason if you start searching for factors starting with 2 and working your way up to the square root, that the first number/i factor that is prime will be the largest prime factor.  If however, none of the factors above the square root are prime, you have to keep checking the lower factors until you reach the square root of the number.  Now if I had my way I would have had an additional method, isPrime, to do that check, but it had to be done in one method.  Here is my code:



Here is the recommended code in the Q&A fourm:



Wow that is simple.  Miles simpler than my method.  And I will further add, I don't know if I ever would have thought of this.  Are there books or courses just on programming techniques that can teach me how to think like that?  I choose not to take the time to test, but I half wonder if the other person's code isn't faster than mine.  I think mine would be faster on largeer numbers as you appoach Integer.MAX_VALUE, but still.  Any thoughts?

~d
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Cone wrote:Any thoughts?


1. Premature optimization is the root of all evil.

2. Write clear and simple code first. Modern compilers have an easier time automatically optimizing clean and simple code. If you write complex code, the compiler will be less likely to optimize it anyway. Then you'll have to manually optimize it.

3. Programmers suck at optimizing by sight and intuition. If you really must eke out every single bit of performance from the program, use a profiler. More often than not, the code you thought was going to be a performance problem isn't and the problem is actually somewhere you didn't think to look.

4. In the long run, complex code that is hard to understand cost organizations more than anything else. This is measured in longer delays in deploying, debugging, maintenance, enhancements, higher number of defects, and lower customer satisfaction. Also, developers don't tend to stick around when codebases are hard to work with so there's also a high cost of attrition and hiring new people and then training them.
 
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Cone wrote:And I will further add, I don't know if I ever would have thought of this.



I looked at that and thought... The largest prime factor of N, eh? Not the smallest, then, but I know how to find that. Okay, it must be N divided by the smallest prime factor. But no, there might be several prime factors. So you'd have to divide N by the smallest prime factor and then carry on finding the largest prime factor of the result of that division.

Which is basically what that short code does. But notice that what I thought had nothing at all to do with Java code. It was just thinking through what needed to be done, not how it would be written in Java. And fortunately the problem is simple enough so that it can be thought through in one go, like I did.

Also, there's a line of code in your short code which I would have missed the first time around. The code I would have written would have started from 60 and found the prime factor 2. Then it would have carried on with 30 and found the prime factor 3, and then it would have carried on with 10 and found the prime factor 5, and ended up with 2. Which is obviously not the largest prime factor of 60! But I wouldn't even have found that problem ("Watch out for prime factors which occur more than once") until some fairly good testing was done to stumble across it. I wasn't careful about what I meant by "carry on" until I noticed what I should have meant instead.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Cone wrote:. . . using the least CPU cycles vs using the simplest code. . . .

That is what C books printed in the 1970s and 1980s taught. Another thing was that screens were very small and it was necessary to cram as much code as possible onto the tiny screens available. More recent experience has taught that this approach is completely mistaken.
  • 1: It costs much more to pay programmers to maintain code than buy extra chips or (more probably) RAM to improve execution speed. Unmaintainable code is not an asset but an expensive liability. I think that is similar to Junilu's point 4.
  • 2: As Junily said, there is a good chance that the programmer's guess at what will run fastest will be wrong.
  • 3: Also Junilu said elsewhere, the compiler can much better optimise straightforward code than something convoluted. Search for “Brian Goetz write dumb code” and you may be lucky and find out more information.
  • . . . factors starting with 2 and working your way up to the square root . . .

    I think you have worked out already, that gets you the smallest prime factor; you want to go from the root downward to find the largest prime factor. Maybe it will be more efficient to have a supply of ready‑made prime numbers, maybe calculated from a Sieve of Eratosthenes. Don't know.

    if none of the factors above the square root are prime . . .

    If i is a factor of j and i > √j, then i can only be a prime number if j is a prime number. If you haven't found any factors by the time you reach √j, you have got a prime number.

    it had to be done in one method. . . .

    That is probably so you can pass the code to an automatic checker to test that the result is correct. Receiving a correct result doesn't constitute proof that the code is correctly written. Also insisting on a particular implementation can force you into bad design, e.g. insisting you use a single method.

    I don't think that choosing an efficient algorithm constitutes premature optimisation. Once you have spent a few minutes thinking about it, it becomes obvious that testing prime numbers in the range 2...√ninc is more efficient than the range 2...n. Have you considered testing for 2 and then the range 3...√n and going up by steps of 2 because from 3 onwards all prime numbers are odd numbers? Than might or might not be quicker. Don't know. Maybe Paul's suggestion, which constitutes factorising the number completely and looking for the lr=argest factor, will be faster or more efficient or clearer; I don't know. Maybe it should be converted to a more OO stye. You have a Factoriseer class with its argument as a field. You can have getAllFactors(), getSmallestFactor(), getLargestFactor(), etc. methods. They can call each other behind the scenes, but you don't let users find that out. You can cache a store of prime factors too, so you don't need to repeat the factorisation process. Again, you don't let users find that out.
     
    reply
      Bookmark Topic Watch Topic
    • New Topic