Why the output is different, java inheritance? - java

I've got 2 classes, car extends vehicle, Why, when I'm trying to print a new created car object the output isn't equal as I thought.
I'm running it on Eclipse, java 11
public class vehicle_13 {
private int years;
public vehicle_13(int y) {
years=y;
}
public int years() {
return years;
}
public String driving() {
return "Can drive";
}
public int speed() {
return 50;
}
public String toString() {
return "years = "+years()+"\n"+this.driving()+"\n"+"speed = "+this.speed()
+"\n"+this.money_per(); // driving() = this.driving()
}
public int money_per() {
return years*10;
}
}
public class car_13 extends vehicle_13 {
public car_13(int y) {
super(0);
}
public int speed() {
System.out.println(super.driving());
return super.speed()*2;
}
}
I expect the output of this car object .toString() to be:
years = 0
Can drive
Can drive
speed = 100
0
but the actual output is:
Can drive
years = 0
Can drive
speed = 100
0

When you concatenate the string like this:
return "years = " + years() + "\n" + this.driving() + "\n"
+ "speed = " + this.speed() + "\n" + this.money_per();
It has to execute each of the methods before it creates the string. After all, it's the result of executing the method that gets added to the string. So the println in the speed method is called when this.speed() is evaluated, then the concatenated string is returned by toString, and then the result is passed to System.out.println. So the println in speed runs before the println in main, not in the middle of it.
P.S: Long concatenation like this, is better suited to the String.format method
return String.format("years = %d\n%d\nspeed = %d\n%d",
years(), driving(), speed(), money_per());

You have called super.driving in the sub-class and that is what is evaluated first. Therefore it prints out "Can drive" first, before the result of the toString as you expected.

Related

Object Oriented Programming, Method Call Not Working as Expected, Subclasses

I am having trouble with my call to the method makeNoise in the Pets class. I call the makeNoise method through another class, Humans, that has a makePetMakeNoise method:
public void makePetMakeNoise()
{
int randnum = (int)(Math.random() *5);
pet.makeNoise(randnum);
}
And I set the pets' canMakeNoise boolean when I create it: Cat a = new Cat("Critter", "Meow", true);
When I call the Humans' makePetMakeNoise method, I only get a printout like so: Critter remains silent instead of: Meow Critter. Why is this, and how do I fix it? Thanks.
public class Pets
{
String name;
String noise;
boolean canMakeNoise;
public Pets(String pname, String pnoise, boolean pcanmakenoise)
{
name = pname;
noise = pnoise;
pcanmakenoise = canMakeNoise;
}
public void makeNoise(int number)
{
if(canMakeNoise==true)
{
for(int i=0; i<number; i++)
{
System.out.println(noise + " " + name);
}
}
else if(canMakeNoise==false)
{
System.out.println(name + " *remains silent*");
}
}
public void eat()
{
System.out.println(name + " is eating...");
}
}
It looks like the assignment for "canMakeNoise" in the constructor is reversed, i.e. assign canmakenoise = pcanmakenoise.
Change this line from
pcanmakenoise = canMakeNoise;
to
canMakeNoise = pcanmakenoise;
You assigned the constructor parameter pcanmakenoise with the value of canMakeNoise which is currently null.
pcanmakenoise = canMakeNoise;
Default boolean value is false.
canMakeNoise is always false; Hence below condition is always called.
else if(canMakeNoise==false)
Reference ::
https://msdn.microsoft.com/en-us/library/83fhsxwc.aspx
https://www.google.com/search?q=c%23+default+boolean+value&ie=utf-8&oe=utf-8

I don't understand the toString method. How can I print the contents of an object?

Generally in java, I know that if we try to print multiple objects (for example objects named Joe, Steve, Richard) like that
System.out.println(Joe);
System.out.println(Steve);
System.out.println(Richard);
the outcome will be the memory location not the object itself. But if I invoke a toString method on only one of them, it will print the object's contents normally and that's what I fail to understand.
Also, if the toString method is a pre-defined method, why do I have to re-write it in my code?
Thank you.
public class Time {
int Hours;
int Minutes;
int Seconds;
public Time(int h, int m, int s){
Hours = h;
Minutes = m;
Seconds = s;
}
public Time(){
Hours = 0;
Minutes = 0;
Seconds = 0;
}
public int hours ( )
{
return Hours ;
}
public int minutes ( )
{
return Minutes ;
}
public int seconds ( )
{
return Seconds;
}
public void addhour ( )
{
if ( Hours == 23)
{
Hours = 0 ;
}
else Hours++;
}
public void addminute ( )
{
if (Minutes == 59)
{
Minutes = 0 ;
addhour ( ) ;
}
else Minutes++;
}
public void addsecond ( )
{
if ( Seconds == 59)
{
Seconds = 0 ;
addminute ( ) ;
}
else Seconds++;
}
public String toString(){
return "Time now is " + Hours + ":" + Minutes + ":" + Seconds;
}
public static void main (String[] args) {
Time t = new Time (23, 59, 59);
Time r = new Time (22, 59, 59);
System.out.println(t) ;
System.out.println(r) ;
t.addhour( );
System.out.println(t) ;
t.addminute( );
System.out.println(t) ;
t.addsecond( ) ;
System.out.println(t.toString());
}
}
the output is :
Time now is 23:59:59
Time now is 22:59:59
Time now is 0:59:59
Time now is 1:0:59
Time now is 1:1:0
You have two things Object and Attributes of Objects if Joe (a person) is Object than height,width,etc. are his Attributes.
System.out.println(Joe);<---it'll print reference
System.out.println(Joe.height);<----It will print attribute assigned to Object
Now point is you don't need to call toString() if you are using System.out.println() because println() do it implicitly for you.
It happens something like this
object.attribute
goes into memory to find reference takes that reference to associate it's attributes and println() calls toString() and prints value.
Your toString() method is overriding the actual method which is there in Object class because Object is Super class of all classes.
public String toString(){
return "Time now is " + Hours + ":" + Minutes + ":" + Seconds;
}
One other way.
If you want to get all attributes of Object you can create method
public String method(YourClass o)
{
return o.hour+":"+o.minute+":"+o.second;
}
the outcome will be the memory location not the object itself.
No if you have not overridden toString() method in your class default toString() method of Object class is used. i.e
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
which prints the classname along with it's hash value.
Also, if the toString method is a pre-defined method, why do I have to re-write it in my code?
It's called overriding and you do it so that when you print the object your custom toString() is called and not the default one which prints class name and it's hash.
It's usually a way to print the internal values of the Object. If you don't re-write it will display the default string representation of the object, which usually is meaningless.
It's not mandatory, but it's usually useful when you're debugging your code OR when you are printing your data in the console.
toString() is predefined for all objects and defaults to the behaviour you describe.
You need to redefine it because your desired behaviour is unique yo you as a programmer. Should object Joe print "Joe", "Joe Beluchi" or "Joe, aged 23years, living in New York".
In your case you would have to override ToString method and customize it in order to print the information you need.
For instance, if you objects were persons, you could override ToString (in Person class) as following:
#Override public class Person {
return "Person{" + "Name=" + this.name + ",
Surname=" + this.surname + ",
Date of birth=" + this.birth + '}';
}

extending a class with an extra parameter

I got a simple question. I have a class, which I use for purpose of splitting a string in 2 years:
public class Period {
int firstYear;
int secondYear;
Period () {
}
Period(String periode) {
String [] periodeSplit = periode.split("-");
this.firstYear = Integer.parseInt(periodeSplit[0]);
this.secondYear = Integer.parseInt(periodeSplit[1]);
}
public String toString() {
return "Firstyear: " + this.firstYear + "\n" + "Secondyear: " + this.secondYear;
}
}
I now want to extend this class, not splitting the data into 2 different ints but into 3 different ints. So besides the 2 already exisiting integer vars I want one extra. Whats the easiest way of doing this?
Your help is appreciated!
Kind regards,
Kipt Scriddy
I think it would be better (and quite easy) the create more general class that will be able to deal with any number of years you pass to it:
public class Period {
int[] years;
Period() {
}
Period(String periode) {
String[] periodeSplit = periode.split("-");
years = new int[periodeSplit.length];
for (int i = 0; i < periodeSplit.length; i++) {
years[i] = Integer.parseInt(periodeSplit[i]);
}
}
public String toString() {
String result = "";
for (int i = 0; i < years.length; i++) {
result += "Year " + i + ":" + years[i] + "\n";
}
return result;
}
}
If the original class really have to be extended than it can be done like this:
class ExtendedPeriod extends Period {
int thirdPart;
ExtendedPeriod(String periode) {
String[] periodeSplit = periode.split("-");
this.firstYear = Integer.parseInt(periodeSplit[0]);
this.secondYear = Integer.parseInt(periodeSplit[1]);
this.thirdPart = Integer.parseInt(periodeSplit[1]);
}
public String toString() {
return "Day: " + this.firstYear + "\n" + "Month: " + this.secondYear
+ "\nYear: " + this.thirdPart;
}
}
I would recommand to change variable names 'firstYear' and 'secondYear' to something different, like 'firstPart', 'secondPart' because for extendedPeriod they aren't years anymore (I left them in my code so it would compile with yours but called the new int 'thirdPart'). I don't feel that this is the best use of inheritance but if that's what's needed. I also wanted to reuse toString from Period like this:
public String toString2() {
return super.toString() + "\nThird part: " + this.thirdPart;
}
but for it to have sense you would have to chagne toString method in Period not to call values 'years'.
When you extend the class, split it into two variables first, the one that's different from your current code, and then the one that your current code would handle.
Then simply call super(periode)
The child class will have access to the parent variables, since you made them default.
I wouldn't extend to just add a new year.
Why not make the entire thing generic enough, so that it supports whatever split you need.
public class Period {
String [] periodeSplit;
Period(String periode) {
periodeSplit = periode.split("-");
}
public String toString() {
//TODO : Iterate and print.
}
}

Calling functions from different classes

I'm writing a program and I'm supposed to check and see if a certain object is in the list before I call it. I set up the contains() method which is supposed to use the equals() method of the Comparable interface I implemented on my Golfer class but it doesn't seem to call it (I put print statements in to check). I can't seem to figure out whats wrong with the code, the ArrayUnsortedList class I'm using to go through the list even uses the correct toString() method I defined in my Golfer class but for some reason it won't use the equals() method I implemented.
//From "GolfApp.java"
public class GolfApp{
ListInterface <Golfer>golfers = new ArraySortedList<Golfer> (20);
Golfer golfer;
//..*snip*..
if(this.golfers.contains(new Golfer(name,score)))
System.out.println("The list already contains this golfer");
else{
this.golfers.add(this.golfer = new Golfer(name,score));
System.out.println("This golfer is already on the list");
}
//From "ArrayUnsortedList.java"
protected void find(T target){
location = 0;
found = false;
while (location < numElements){
if (list[location].equals(target)) //Where I think the problem is
{
found = true;
return;
}
else
location++;
}
}
public boolean contains(T element){
find(element);
return found;
}
//From "Golfer.java"
public class Golfer implements Comparable<Golfer>{
//..irrelavant code sniped..//
public boolean equals(Golfer golfer)
{
String thisString = score + ":" + name;
String otherString = golfer.getScore() + ":" + golfer.getName() ;
System.out.println("Golfer.equals() has bee called");
return thisString.equalsIgnoreCase(otherString);
}
public String toString()
{
return (score + ":" + name);
}
My main problem seems to be getting the find function of the ArrayUnsortedList to call my equals function in the find() part of the List but I'm not exactly sure why, like I said when I have it printed out it works with the toString() method I implemented perfectly.
I'm almost positive the problem has to do with the find() function in the ArraySortedList not calling my equals() method. I tried using some other functions that relied on the find() method and got the same results.
Your equals method should take an Object argument, not a Golfer. The equals(Golfer) method is overloading the Comparable's equals(Object) method but does not implement it. It's simply an overloaded method no other code knows about, so it doesn't get called.
public boolean equals(Object obj)
{
if(!(obj instanceof Golfer)) return false;
Golfer golfer = (Golfer)obj;
String thisString = score + ":" + name;
String otherString = golfer.getScore() + ":" + golfer.getName() ;
System.out.println("Golfer.equals() has bee called");
return thisString.equalsIgnoreCase(otherString);
}

Getting the name of the currently executing method

Is there a way to get the name of the currently executing method in Java?
Technically this will work...
String name = new Object(){}.getClass().getEnclosingMethod().getName();
However, a new anonymous inner class will be created during compile time (e.g. YourClass$1.class). So this will create a .class file for each method that deploys this trick. Additionally, an otherwise unused object instance is created on each invocation during runtime. So this may be an acceptable debug trick, but it does come with significant overhead.
An advantage of this trick is that getEnclosingMethod() returns java.lang.reflect.Method which can be used to retrieve all other information of the method including annotations and parameter names. This makes it possible to distinguish between specific methods with the same name (method overload).
Note that according to the JavaDoc of getEnclosingMethod() this trick should not throw a SecurityException as inner classes should be loaded using the same class loader. So there is no need to check the access conditions even if a security manager is present.
Please be aware: It is required to use getEnclosingConstructor() for constructors. During blocks outside of (named) methods, getEnclosingMethod() returns null.
Thread.currentThread().getStackTrace() will usually contain the method you’re calling it from but there are pitfalls (see Javadoc):
Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this thread is permitted to return a zero-length array from this method.
January 2009:
A full code would be (to use with #Bombe's caveat in mind):
/**
* Get the method name for a depth in call stack. <br />
* Utility function
* #param depth depth in the call stack (0 means current method, 1 means call method, ...)
* #return method name
*/
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
//System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
// return ste[ste.length - depth].getMethodName(); //Wrong, fails for depth = 0
return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
}
More in this question.
Update December 2011:
bluish comments:
I use JRE 6 and gives me incorrect method name.
It works if I write ste[2 + depth].getMethodName().
0 is getStackTrace(),
1 is getMethodName(int depth) and
2 is invoking method.
virgo47's answer (upvoted) actually computes the right index to apply in order to get back the method name.
We used this code to mitigate potential variability in stack trace index - now just call methodName util:
public class MethodNameTest {
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
i++;
if (ste.getClassName().equals(MethodNameTest.class.getName())) {
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static void main(String[] args) {
System.out.println("methodName() = " + methodName());
System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
}
public static String methodName() {
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
}
}
Seems overengineered, but we had some fixed number for JDK 1.5 and were a bit surprised it changed when we moved to JDK 1.6. Now it's the same in Java 6/7, but you just never know. It is not proof to changes in that index during runtime - but hopefully HotSpot doesn't do that bad. :-)
Both of these options work for me with Java:
new Object(){}.getClass().getEnclosingMethod().getName()
Or:
Thread.currentThread().getStackTrace()[1].getMethodName()
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
name will have value foo.
The fastest way I found is that:
import java.lang.reflect.Method;
public class TraceHelper {
// save it static to have it available on every call
private static Method m;
static {
try {
m = Throwable.class.getDeclaredMethod("getStackTraceElement",
int.class);
m.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getMethodName(final int depth) {
try {
StackTraceElement element = (StackTraceElement) m.invoke(
new Throwable(), depth + 1);
return element.getMethodName();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
It accesses the native method getStackTraceElement(int depth) directly. And stores the accessible Method in a static variable.
This can be done using StackWalker since Java 9.
public static String getCurrentMethodName() {
return StackWalker.getInstance()
.walk(s -> s.skip(1).findFirst())
.get()
.getMethodName();
}
public static String getCallerMethodName() {
return StackWalker.getInstance()
.walk(s -> s.skip(2).findFirst())
.get()
.getMethodName();
}
StackWalker is designed to be lazy, so it's likely to be more efficient than, say, Thread.getStackTrace which eagerly creates an array for the entire callstack. Also see the JEP for more information.
Use the following Code :
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
String methodName = e.getMethodName();
System.out.println(methodName);
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
}
This is an expansion on virgo47's answer (above).
It provides some static methods to get the current and invoking class / method names.
/* Utility class: Getting the name of the current executing method
* https://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method
*
* Provides:
*
* getCurrentClassName()
* getCurrentMethodName()
* getCurrentFileName()
*
* getInvokingClassName()
* getInvokingMethodName()
* getInvokingFileName()
*
* Nb. Using StackTrace's to get this info is expensive. There are more optimised ways to obtain
* method names. See other stackoverflow posts eg. https://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection/2924426#2924426
*
* 29/09/2012 (lem) - added methods to return (1) fully qualified names and (2) invoking class/method names
*/
package com.stackoverflow.util;
public class StackTraceInfo
{
/* (Lifted from virgo47's stackoverflow answer) */
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste: Thread.currentThread().getStackTrace())
{
i++;
if (ste.getClassName().equals(StackTraceInfo.class.getName()))
{
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static String getCurrentMethodName()
{
return getCurrentMethodName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentMethodName(int offset)
{
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getMethodName();
}
public static String getCurrentClassName()
{
return getCurrentClassName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentClassName(int offset)
{
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getClassName();
}
public static String getCurrentFileName()
{
return getCurrentFileName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentFileName(int offset)
{
String filename = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getFileName();
int lineNumber = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getLineNumber();
return filename + ":" + lineNumber;
}
public static String getInvokingMethodName()
{
return getInvokingMethodName(2);
}
private static String getInvokingMethodName(int offset)
{
return getCurrentMethodName(offset + 1); // re-uses getCurrentMethodName() with desired index
}
public static String getInvokingClassName()
{
return getInvokingClassName(2);
}
private static String getInvokingClassName(int offset)
{
return getCurrentClassName(offset + 1); // re-uses getCurrentClassName() with desired index
}
public static String getInvokingFileName()
{
return getInvokingFileName(2);
}
private static String getInvokingFileName(int offset)
{
return getCurrentFileName(offset + 1); // re-uses getCurrentFileName() with desired index
}
public static String getCurrentMethodNameFqn()
{
return getCurrentMethodNameFqn(1);
}
private static String getCurrentMethodNameFqn(int offset)
{
String currentClassName = getCurrentClassName(offset + 1);
String currentMethodName = getCurrentMethodName(offset + 1);
return currentClassName + "." + currentMethodName ;
}
public static String getCurrentFileNameFqn()
{
String CurrentMethodNameFqn = getCurrentMethodNameFqn(1);
String currentFileName = getCurrentFileName(1);
return CurrentMethodNameFqn + "(" + currentFileName + ")";
}
public static String getInvokingMethodNameFqn()
{
return getInvokingMethodNameFqn(2);
}
private static String getInvokingMethodNameFqn(int offset)
{
String invokingClassName = getInvokingClassName(offset + 1);
String invokingMethodName = getInvokingMethodName(offset + 1);
return invokingClassName + "." + invokingMethodName;
}
public static String getInvokingFileNameFqn()
{
String invokingMethodNameFqn = getInvokingMethodNameFqn(2);
String invokingFileName = getInvokingFileName(2);
return invokingMethodNameFqn + "(" + invokingFileName + ")";
}
}
To get the name of the method that called the current method you can use:
new Exception("is not thrown").getStackTrace()[1].getMethodName()
This works on my MacBook as well as on my Android phone
I also tried:
Thread.currentThread().getStackTrace()[1]
but Android will return "getStackTrace"
I could fix this for Android with
Thread.currentThread().getStackTrace()[2]
but then I get the wrong answer on my MacBook
Util.java:
public static String getCurrentClassAndMethodNames() {
final StackTraceElement e = Thread.currentThread().getStackTrace()[2];
final String s = e.getClassName();
return s.substring(s.lastIndexOf('.') + 1, s.length()) + "." + e.getMethodName();
}
SomeClass.java:
public class SomeClass {
public static void main(String[] args) {
System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
}
}
An alternative method is to create, but not throw, an Exception, and use that object from which to get the stack trace data, since the enclosing method will typically be at index 0 - as long as the JVM stores that information, as others have mentioned above. This not the cheapest method, however.
From Throwable.getStackTrace() (this has been the same since Java 5 at least):
The zeroth element of the array (assuming the array's length is non-zero) represents the top of the stack, which is the last method invocation in the sequence. Typically, this is the point at which this throwable was created and thrown.
The snippet below assumes the class is non-static (because of getClass()), but that's an aside.
System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
I've got solution using this (In Android)
/**
* #param className fully qualified className
* <br/>
* <code>YourClassName.class.getName();</code>
* <br/><br/>
* #param classSimpleName simpleClassName
* <br/>
* <code>YourClassName.class.getSimpleName();</code>
* <br/><br/>
*/
public static void getStackTrace(final String className, final String classSimpleName) {
final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
int index = 0;
for (StackTraceElement ste : steArray) {
if (ste.getClassName().equals(className)) {
break;
}
index++;
}
if (index >= steArray.length) {
// Little Hacky
Log.w(classSimpleName, Arrays.toString(new String[]{steArray[3].getMethodName(), String.valueOf(steArray[3].getLineNumber())}));
} else {
// Legitimate
Log.w(classSimpleName, Arrays.toString(new String[]{steArray[index].getMethodName(), String.valueOf(steArray[index].getLineNumber())}));
}
}
I don't know what is the intention behind getting the currently executed method's name, but if that's just for debugging purpose, then logging frameworks like "logback" can help here. For example, in logback, all you need to do is to use the pattern "%M" in your logging configuration. However, this should be used with caution as this may degrade performance.
Just in case the method which name you want to know is a junit test method, then you can use junit TestName rule: https://stackoverflow.com/a/1426730/3076107
I use this code snippet with the latest Android Studio with the latest Java update. It can be called from any Activity, Fragment, etc.
public static void logPoint() {
String[] splitPath = Thread.currentThread().getStackTrace()[3]
.toString().split("\\.");
Log.d("my-log", MessageFormat.format("{0} {1}.{2}",
splitPath[splitPath.length - 3],
splitPath[splitPath.length - 2],
splitPath[splitPath.length - 1]
));
}
call it like this
logPoint();
output
... D/my-log: MainActivity onCreate[(MainActivity.java:44)]
Most answers here seems wrong.
public static String getCurrentMethod() {
return getCurrentMethod(1);
}
public static String getCurrentMethod(int skip) {
return Thread.currentThread().getStackTrace()[1 + 1 + skip].getMethodName();
}
Example:
public static void main(String[] args) {
aaa();
}
public static void aaa() {
System.out.println("aaa -> " + getCurrentMethod( ) );
System.out.println("aaa -> " + getCurrentMethod(0) );
System.out.println("main -> " + getCurrentMethod(1) );
}
Outputs:
aaa -> aaa
aaa -> aaa
main -> main
I rewritten a little the maklemenz's answer:
private static Method m;
static {
try {
m = Throwable.class.getDeclaredMethod(
"getStackTraceElement",
int.class
);
}
catch (final NoSuchMethodException e) {
throw new NoSuchMethodUncheckedException(e);
}
catch (final SecurityException e) {
throw new SecurityUncheckedException(e);
}
}
public static String getMethodName(int depth) {
StackTraceElement element;
final boolean accessible = m.isAccessible();
m.setAccessible(true);
try {
element = (StackTraceElement) m.invoke(new Throwable(), 1 + depth);
}
catch (final IllegalAccessException e) {
throw new IllegalAccessUncheckedException(e);
}
catch (final InvocationTargetException e) {
throw new InvocationTargetUncheckedException(e);
}
finally {
m.setAccessible(accessible);
}
return element.getMethodName();
}
public static String getMethodName() {
return getMethodName(1);
}
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
What's wrong with this approach:
class Example {
FileOutputStream fileOutputStream;
public Example() {
//System.out.println("Example.Example()");
debug("Example.Example()",false); // toggle
try {
fileOutputStream = new FileOutputStream("debug.txt");
} catch (Exception exception) {
debug(exception + Calendar.getInstance().getTime());
}
}
private boolean was911AnInsideJob() {
System.out.println("Example.was911AnInsideJob()");
return true;
}
public boolean shouldGWBushBeImpeached(){
System.out.println("Example.shouldGWBushBeImpeached()");
return true;
}
public void setPunishment(int yearsInJail){
debug("Server.setPunishment(int yearsInJail=" + yearsInJail + ")",true);
}
}
And before people go crazy about using System.out.println(...) you could always, and should, create some method so that output can be redirected, e.g:
private void debug (Object object) {
debug(object,true);
}
private void dedub(Object object, boolean debug) {
if (debug) {
System.out.println(object);
// you can also write to a file but make sure the output stream
// ISN'T opened every time debug(Object object) is called
fileOutputStream.write(object.toString().getBytes());
}
}

Categories

Resources