一、静态方法和实例方法
1)区别
1.在外部调用静态方法时(比如main()就是一个典型的静态方法),可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。调用静态方法可以无需创建对象
2.在静态方法内调用其它方法和变量时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法,如果需要调用,则需要先实例化
注:区别多多,只提两点特别重要的
2)实例说明
public class Test {
public static String staticStruct(){ return "这是一个静态方法"; }
public String noStaticStruct(){return "这是一个实例方法";}
//情况一:非静态方法 调用 静态方法和实例方法
public void struct(){
//本类调用情况
System.out.println(staticStruct());//同一个类中非静态方法调用静态方法直接 方法名 方式调用
System.out.println(noStaticStruct());//同一个类中非静态方法调用非静态方法直接 方法名 方式调用
//其它类调用情况
System.out.println(Test0.staticStruct());//不同类中非静态方法调用静态方法直接 类名.方法名 方式调用
Test0 test0 = new Test0();
System.out.println(test0.noStaticStruct());//不同类中非静态方法调用非静态方法,对象名.方法名 方式调用
}
//情况二:静态方法 调用 静态方法和实例方法
public static void main(String[] args) {
//本类调用情况
System.out.println(staticStruct());//同一个类中静态方法调用静态方法,直接 方法名 方式调用
Test test = new Test();
System.out.println(test.noStaticStruct());//同一个类中静态方法调用非静态方法,对象名.方法名 方式调用
//调用其它类情况
System.out.println(Test0.staticStruct());//不同类中静态方法调用静态方法,直接 类名.方法名 方式调用
Test0 test0 = new Test0();
System.out.println(test0.noStaticStruct());//不同类中静态方法调用非静态方法,对象名.方法名 方式调用
}
}
public class Test0 {
public static String staticStruct(){ return "这是其它类的一个静态方法"; }
public String noStaticStruct(){
return "这是其它类一个实例方法";
}
}
3)使用场景
静态方法和实例方法:
1、从逻辑关系来看:(优先级2)
若方法与类的实例不存在逻辑上的联系,那么用静态方法。
反之则最好使用实例化方法。
2、从性能角度:(优先级3)
若方法经常被调用,则用静态方法更佳,因为这样可以避免频繁地实例化对象导致的资源占用,提高性能。
然而,由于静态的东西,在构造的时候是在堆中声称的,在结束之前不会被释放与改变,会一直占用内存空间,所以不宜有过多的静态成员。
因此若方法不会经常被调用,则使用实例方法可能会更好。
3、从线程并发的角度考虑:(优先级1)
要考虑方法是否存在严重的并发,
如果并发的可能性很大,则不适宜使用静态方法。
如果并发的可能性很小,或者通过简单的同步操作可以保证线程安全,那就可以考虑使用静态方法,这种情况下,静态方法要更快,更方便。
总结:
考量采用何种方式,要看主要矛盾在什么地方。
所以应该在保证不会产生并发的情况下,在方便快捷和开发难度上做一个衡量
二、构造方法
特点:
1.方法名与类名相同(首字母大写)。没有返回值和类型(例如return、void等)。不能被static、final、native、abstract和synchronized修饰
2.一个类中可以有多个构造方法,通过重载来实现
3.不能被子类继承,但是子类可以通过super()方法来调用父类无入参的构造方法;也可以通过super(入参)来调用父类有入参的构造方法
4.构造方法通过this()或者this(入参)来调用本类其它的构造方法
5.在程序中通过new语句调用,new语句能根据入参来判定调用哪个构造方法。特别注意:通过super()方法来调用父类构造方法的,只要new,就强制执行
实例说明:
情况一:不考虑继承
public class Test {
public Test(){
System.out.println("构造方法一:无入参");
}
public Test(String str){
System.out.println("构造方法二:有str入参");
}
public Test(int in){
System.out.println("构造方法三:有int入参");
}
/**
* 实例化有构造方法的类,根据入参直接就强制运行了里面的构造方法
* @param args
*/
public static void main(String[] args){
Test test0 = new Test();
Test test1 = new Test("111");
Test test2 = new Test(111);
}
}
结果返回:
构造方法一:无入参 //对应Test test0 = new Test()结果
构造方法二:有str入参 //对应Test test1 = new Test("111")结果
构造方法三:有int入参 //对应Test test2 = new Test(111)结果
情况二:只考虑继承
public class TestDemo extends Test {
public TestDemo(){
super();
}
public TestDemo(String str){
super(str);
}
public TestDemo(int in){
super(in);
}
public static void main(String[] args) {
TestDemo testDemo = new TestDemo();
TestDemo testDemo1 = new TestDemo("1111");
TestDemo testDemo2 = new TestDemo(1111);
}
}
结果返回:
构造方法一:无入参 //TestDemo testDemo = new TestDemo()结果
构造方法二:有str入参 //TestDemo testDemo1 = new TestDemo("1111")结果
构造方法三:有int入参 //TestDemo testDemo2 = new TestDemo(1111)结果
情况三:掉同类中的构造方法
public class Test {
public Test(){
System.out.println("构造方法一:无入参");
}
public Test(String str){
this();
}
public Test(int in){
this();
}
public static void main(String[] args) {
Test test = new Test();
Test test1 = new Test("1111");
Test test2 = new Test(1111);
}
}
结果返回:
构造方法一:无入参 //Test test = new Test()结果
构造方法一:无入参 //Test test1 = new Test("1111")结果
构造方法一:无入参 //Test test1 = new Test(1111)结果
情况四:以上三种情况结合(上述三种情况理解透彻后,第四种情况的运行结果一目了然)
/*
* 父类构造方法
*/
public class Struct {
private int a;
public Struct() {
System.out.println("<<<<<<<<<我是Struct类中普通的构造方法<<<<<<<<<<");
}
public Struct(int a) {
this.a = a;
System.out.println("<<<<<<<<<我是Struct类中带入参的构造方法"+a+"<<<<<<<<<<");
}
}
/**
* 构造方法使用
*/
public class DoStruct extends Struct{
//无入参构造方法
public DoStruct() {
System.out.println("<<<<<<<<我是DoStruct类中的构造方法<<<<<<<<<");
}
//通过super()来调用父类中的无参数构造方法,父类的构造方法是不会被子类继承的
//通过super(111111)来调用父类中的有参数构造方法,父类的构造方法是不会被子类继承的
public DoStruct(int a) {
super(1111111);
}
//有入参构造方法
public DoStruct(String b) {
this();
System.out.println("<<<<<<<<我是DoStruct类中带入参的构造方法"+b+"<<<<<<<<<");
}
//通过new调用构造方法
public static void main(String[] args) {
//无入参new,执行的是 不带入参的构造方法、继承父类的构造方法。带入参的本类构造方法不执行
System.out.println("一、不带入参调用构造函数");
DoStruct doStruct = new DoStruct();
//带String入参的new,执行的是 本类带入参的构造方法、继承父类的构造方法。不带入参的本类构造方法不执行
System.out.println("二、带String入参调用构造函数(本类构造方法)");
DoStruct doStruct2 = new DoStruct("123456");
//带int入参的new,执行的是 父类带入参的构造方法、继承父类的构造方法。不带入参的本类构造方法不执行,带String入参的本类构造方法也不执行
System.out.println("三、带int入参调用构造函数(父类构造方法)");
DoStruct doStruct3 = new DoStruct(123456);
}
}
结果:
一、不带入参调用构造函数
<<<<<<<<<我是Struct类中普通的构造方法<<<<<<<<<<
<<<<<<<<我是DoStruct类中的构造方法<<<<<<<<<
二、带String入参调用构造函数(本类构造方法)
<<<<<<<<<我是Struct类中普通的构造方法<<<<<<<<<<
<<<<<<<<我是DoStruct类中的构造方法<<<<<<<<<
<<<<<<<<我是DoStruct类中带入参的构造方法123456<<<<<<<<<
三、带int入参调用构造函数(父类构造方法)
<<<<<<<<<我是Struct类中带入参的构造方法1111111<<<<<<<<<<
总结:
静态方法和实例方法被调用上的区别:
1)静态方法被调用时不需要new对象
2)实例方法被调用时只有本类中调用不需要new对象,其它情况下都需要new对象
构造方法被调用:
1)跟在关键字new后面,类名加上一个小括号(),小括号内根据实际加上实参
2)跟在关键字super或this后加上一个小括号(),小括号内根据实际添加实参,super和this必须放在第一行
例:最常用的使用场景就是类中的get和set构造函数,在类new对象时就已经运行了get,set方法,极大的减少了代码量