实例方法

实例方法是需要在调用之前创建其类的对象的方法。要调用实例方法,我们必须创建在其中定义它的类的对象。 

内存分配: 

        这些方法本身存储在堆的永久代空间中,但参数(传递给它们的参数)及其局部变量和要返回的值在堆栈中分配。它们可以在它们所在的同一个类中调用,也可以从定义在同一个包或其他包中的不同类中调用,这取决于提供给所需实例方法的访问类型

要点: 

  • 实例方法属于类的对象,而不属于类,即它们可以在创建类的对象后调用。
  • 实例方法不是在每个实例的基础上存储的,即使使用虚拟方法也是如此。它们存储在一个单独的内存位置,它们只“知道”它们属于哪个对象,因为在调用它们时会传递这个指针。
  • 它们可以被覆盖,因为它们是在运行时使用动态绑定解析的。

下面是访问实例方法的实现:

package org.jake.demo.utils;

public class InstanceUtils {

	public String name = "";

	/**
	 * 在同一个类中或者从同一个包或不同包中定义的另一个类中调用的实例方法。
	 * 
	 * @param name
	 */
	public void getName(String name) {
		this.name = name;
	}
}

package org.jake.demo;

import org.jake.demo.utils.InstanceUtils;

public class App {
	public static void main(String[] args) {
		InstanceUtils instanceUtils1 = new InstanceUtils();
		InstanceUtils instanceUtils2 = new InstanceUtils();
		instanceUtils1.getName("instanceUtilsName1");
		instanceUtils2.getName("instanceUtilsName2");
		System.out.println(instanceUtils1.name);
		System.out.println(instanceUtils2.name);

	}
}

输出:

instanceUtilsName1
instanceUtilsName2

静态方法

静态方法是Java中不需要创建类对象就可以调用的方法。它们由类名本身或对该类的对象的引用来引用。  

内存分配: 

它们存储在堆的永久代空间中,因为它们与它们所在的类相关联,而不是与该类的对象相关联。但是它们的局部变量和传递给它们的参数都存储在堆栈中。由于它们属于类,因此可以在不创建类的对象的情况下调用它们。

要点:  

  • 静态方法与它们所在的类相关联,即调用它们时无需创建类的实例,即ClassName.methodName(args)
  • 它们的设计目的是在从同一类创建的所有对象之间共享。
  • 静态方法不能被覆盖,因为它们是由编译器在编译时使用静态绑定解析的。但是,我们可以在超类子类中将同名方法声明为静态,但它会被称为方法隐藏,因为派生类方法将隐藏基类方法。

下面是访问静态方法的实现: 

package org.jake.demo.utils;

public class StaticUtils {
	public static String name = "";

	public static void getName(String name) {
		StaticUtils.name = name;
	}
}

package org.jake.demo;

import org.jake.demo.utils.StaticUtils;

public class App {
	public static void main(String[] args) {

		StaticUtils.getName("staticUtilsName");
		StaticUtils.getName("staticUtilsName");
		System.out.println(StaticUtils.name);
		System.out.println(StaticUtils.name);
	}
}

输出:

staticUtilsName
staticUtilsName

注意:类中定义的静态变量及其值(原语或引用)存储在内存的永久代空间中。 

在第一行中,值 1 将存储在 PermGen 部分。在第二行中,引用 obj 将存储在 PermGen 部分,而它引用的 Object 将存储在堆部分。

什么时候使用静态方法? 

  • 当您拥有可以在同一类的所有实例之间共享的代码时,将该部分代码放入静态方法中。
  • 它们基本上用于访问类的静态字段。

实例方法 vs 静态方法

  • 实例方法可以直接访问实例方法和实例变量。
  • 实例方法可以直接访问静态变量和静态方法。
  • 静态方法可以直接访问静态变量和静态方法。
  • 静态方法不能直接访问实例方法和实例变量。他们必须使用对对象的引用。并且静态方法不能使用this关键字,因为没有引用 'this' 的实例。

this静态字段报错:

package org.jake.demo.utils;

public class StaticUtils {
	public static String name = "";

	public static void getName(String name) {
		this.name = name;
	}
}

package org.jake.demo.utils;

public class InstanceUtils {

	public String name = "";

	/**
	 * 在同一个类中或者从同一个包或不同包中定义的另一个类中调用的实例方法。
	 * 
	 * @param name
	 */
	public void getName(String name) {
		this.name = name;
	}
}

package org.jake.demo;

import org.jake.demo.utils.InstanceUtils;
import org.jake.demo.utils.StaticUtils;

public class App {
	public static void main(String[] args) {
		InstanceUtils instanceUtils1 = new InstanceUtils();
		InstanceUtils instanceUtils2 = new InstanceUtils();
		instanceUtils1.getName("instanceUtilsName1");
		instanceUtils2.getName("instanceUtilsName2");
		System.out.println(instanceUtils1.name);
		System.out.println(instanceUtils2.name);

		StaticUtils.getName("staticUtilsName");
		StaticUtils.getName("staticUtilsName");
		System.out.println(StaticUtils.name);
		System.out.println(StaticUtils.name);
	}
}

输出:

instanceUtilsName1
instanceUtilsName2
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	Cannot use this in a static context

	at org.jake.demo.utils.StaticUtils.getName(StaticUtils.java:7)
	at org.jake.demo.App.main(App.java:15)

注意:在作为工具类时,实例方法和静态方法,要考虑线程安全和内存分配问题。