网站开发 有哪些优化功能,科技公司网站建设,重庆网站建设模板服务,电商平台app大全不同于 C #xff0c;Java 是一门面向对象的编程语言。C 也有面向对象的内容#xff0c;但是 C 和 Java 在方法的具体实现上存在区别。
方法的定义 方法(method)是为执行一个复杂操作组合在一起的语句集合。一个类中可以声明多个方法。其语法是采用 BNF 范式#xff08;Bac… 不同于 C Java 是一门面向对象的编程语言。C 也有面向对象的内容但是 C 和 Java 在方法的具体实现上存在区别。
方法的定义 方法(method)是为执行一个复杂操作组合在一起的语句集合。一个类中可以声明多个方法。其语法是采用 BNF 范式Backus-Naur Form巴科斯范式描述的用来描述计算机语言语法的符号集。 例如下面是一个求两个整数中最大值的方法max
public static int max(int num1,int num2){int result 0;if(num1 num2)result num1;elseresult num2;return result;
}其中public和static是修饰符int是返回值max是方法名称。 方法签名Method Signature是指方法名称形参列表如上面方法的签名就是max(int num1,int num2)。一个类中不能包含方法签名相同的多个方法因为这样在调用方法时编译器不知道要调用哪个。
方法的调用 Java 类中的成员方法可以分为构造方法、类方法和对象方法。
构造方法的调用 构造方法只能在新建一个对象时由 Java 虚拟机进行调用。创建对象通常是通过类名 对象名 new 类名(构造函数的参数)建立。比如下面的例子
class TestConstructor{private int value;public TestConstructor(){this.value 1;}public TestConstructor(int value){this.value value;}public int getValue(){return this.value;}
}public class CallConstructor{public static void main(String[ ] args) {TestConstructor tc new TestConstructor();System.out.println(Value: tc.getValue());tc new TestConstructor(5);System.out.println(Value: tc.getValue());}
}运行的结果是
Value: 1
Value: 5this 调用 可以通过this调用该类的其它构造函数但是必须是构造函数的第一条语句。例如
class TestConstructor{private int value;public TestConstructor(){this(114);}public TestConstructor(int value){this.value value;}public int getValue(){return this.value;}
}public class ThisConstructor{public static void main(String[ ] args) {TestConstructor tc new TestConstructor();System.out.println(Value: tc.getValue());}
}运行的结果为Value: 114。这是因为在调用无参数构造函数时无参构造函数通过this(114)调用了构造函数TestConstructor(int value)并给其形参传递值value 114从而使得value成员初始化为114。
super 调用 一个类还能够通过super调用其父类的构造函数。例如
class TestConstructor{private int value;public TestConstructor(){this(114);}public TestConstructor(int value){this.value value;}public int getValue(){return this.value;}
}public class SuperConstructor extends TestConstructor{public SuperConstructor(){super(514);}public static void main(String[ ] args) {SuperConstructor sc new SuperConstructor();System.out.println(Value: sc.getValue());}
}运行的结果为Value: 514。这是因为在调用SuperConstructor类的午餐构造函数时通过super(514)语句调用了父类TestConstructor中的含参构造函数TestConstructor(int value)并给其形参传递值value 514从而使成员value初始化为514。
类方法的调用 类方法就是由static修饰的方法也称静态方法。静态方法可以通过类名调用也可以通过对象实例调用。比如下面的代码
import java.lang.Math;
public class CallStaticMethod{public static void main(String[] args){int a 114,b 514;System.out.println(Math.max(a,b));}
}在这里调用了 Java 中自带的类Math中的方法max输出的结果为514。可以看到静态方法max是通过类名.方法名的方式调用的max方法不需要通过创造Math对象math并通过math.max(a,b)来调用因为计算一个最大值没有必要依赖对象。 事实上Java 的开发者也考虑到了这一点所以将Math类的构造函数设置为私有的这就导致我们其实也无法创造一个Math类的实例对象。
对象方法的调用 对象方法只能通过实例对象来调用。比如下面的代码
class Wallet{private int money;Wallet(){money 0;}public void addMoney(int amount){this.money amount;}public int getMoney(){return this.money;}
}public class CallObjectMethod{public static void main(String[] args){Wallet wallet new Wallet();System.out.println(Now we have money: wallet.getMoney());wallet.addMoney(520);System.out.println(Then we have money: wallet.getMoney());}
}运行结果为
Now we have money: 0
Then we have money: 520可以看到实例方法addMoney和getMoney都是通过对象名.方法名调用的。显然不能通过Wallet.addmoney或者Wallet.getMoney调用这两个方法因为我可以有多个Wallet对象wallet1,wallet2,...使用类名.方法名无法知道调用的是哪个Wallet对象。
方法的重载 方法重载(Overloading)是指方法名称相同但形参列表不同的方法。仅返回类型不同的方法不是合法的重载。一个类中可以包含多个重载的方法同名的方法可以重载多个版本。
方法重载实例 方法重载例如
public class InputCheckTest{public static void CheckInput(String s){System.out.println(You entered a string.);}public static void CheckInput(int i){System.out.println(You entered an integer.);}public static void CheckInput(double d){System.out.println(You entered a double.);}public static void main(String[] args){CheckInput(114514);CheckInput(114514);CheckInput(114514.0);}
}运行结果:
You entered an integer.
You entered a string.
You entered a double.有歧义的重载 系统根据我们的输入自动判断调用哪个方法。但是有时候可能会有多个合适的方法。例如
public class AmbiguousOverloading {public static void main(String[ ] args) {// System.out.println(max(1, 2));}public static double max(int num1, double num2) {return (num1 num2)?num1:num2;}public static double max(double num1, int num2) {return (num1 num2)?num1:num2;}
}将注释符号去掉上面的代码编译时将产生错误因为编译器不知道max(1,2)调用的是哪个函数。
包和类的导入 Java 源程序在开头通过import 包名;语句导入其它包类可以使用其它包中的类及其方法。有点类似于 C/C 中的#include 头文件名语句。Java 程序在编译时会自动导入java.lang.System类所以我们在编写源程序时可以直接使用System.out和System.in以及它们的方法。 总的来说import有两种类型单类型导入和按需类型导入。
单类型导入 把导入的标识符引入到当前.java文件因此当前文件里不能定义同名的标识符类似C中的 using nm::id; 把名字空间nm的名字id引入到当前代码处。 比如在包p1中定义了类A
package p1;
public class A{// some statements...
}那么在包p2中
package p2;
import p1.A;//单类型导入把p1.A引入到当前域
//这个时候当前文件里不能定义A下面语句编译报错
public class A {//some statements...
}按需类型导入 不是把包里的标识符都引入到当前.java文件只是使包里名字都可见使得我们要使用引入包里的名字时可以不用使用完全限定名因此在当前.java文件里可以定义与引入包里同名的标识符。但二义性只有当名字被使用时才被检测到。类似于C里的using nm。 比如包p1还是和上面一样此时p2中
package p2;
import p1.*; //按需导入没有马上把p1.A引入到当前域
//因此当前文件里可以定义A
public class A {public static void main(String[] args){A a1 new A(); //这时A是p2.ASystem.out.println(a1 instanceof p2.A); //true//当前域已经定义了A因此要想使用package p1里的A只能用完全限定名p1.A a2 new p1.A();}
}如果出现了名字冲突要用完全限定名消除冲突。
类及其方法的可见性修饰符 Java 中的可见性修饰符有private、public和protected不加可见性修饰符的方法默认访问权限为包级。Java 继承时无继承控制(即都是公有继承和 C 不同)故父类成员继承到派生类时访问权限保持不变除了私有。 成员访问控制符的作用
private 只能被当前类定义的函数访问。包级无修饰符的成员只能被同一包中的类访问。protected子类、同一包中的类的函数可以访问。public 所有类的函数都可以访问。
访问权限本类本包子类它包publicYesYesYesYesprotectedYesYesYesNo非子类时包级默认YesYesNo非本包时NoprivateYesNoNoNo 其它的都很好理解只是需要注意一点子类类体中可以访问从父类继承来的protected成员。但如果子类和父类不在同一个包里子类里不能访问另外父类实例的protected成员。可以举一个例子说明这一点。我们在p1包里定义C1类
package p1;
public class C1{protected int u 3;
}然后在包p2中会出现以下情况
package p2;
import p1.C1
public class C2 extends C1{int u 5;public static void main(String[] args){System.out.println(u) // OK. u 相当于 this.u打印结果是 5。System.out.println(super.u) // OK. super.u 指的是父类 C1 中的 u在子类中能够访问。打印结果是 3。C1 o new C1();System.out.println(o.u) // ERROR. 虽然这里是 C1 的子类但是与 C1 不在同一个包中且 o 是一个另外的父类实例不能访问 o 的保护成员。}
}类的继承 Java 中可以用 extends 关键字表示继承在上面举的例子中也能看到。子类对象是一个父类对象即子类对象实例 instanceof 父类名的结果为true。
方法覆盖与方法隐藏 如果子类重新定义了从父类中继承的实例方法称为方法覆盖(Method Override)。如果子类重新定义了从父类中继承的类方法称为方法隐藏(Method Hidden)。它们具有如下性质
仅当父类方法在子类里是可访问的该实例方法才能被子类覆盖/隐藏否则只是定义了一个普通方法而已不叫作覆盖/隐藏。父类的final方法不能被子类覆盖/隐藏否则编译时会报错。在子类函数中可以使用super调用被覆盖的父类方法。
实例方法的多态性 之所以会产生实例方法的多态性这个概念是因为父类引用变量可以指向子类对象。例如如果A是B的父类那么A o new B()是可行的。其中A是变量o的声明类型编译时对有关变量o的语句进行检查时都是将o视作声明类型B是o的运行时类型在运行的时候因为o实际指向的对象并不是A类型的这就会产生多态性。 实例方法的多态性可以通过下面的代码说明
class A{public void m() {System.out.println(As m);}public static void s() {System.out.println(As s);}
}
class B extends A{//覆盖父类实例方法public void m() {System.out.println(Bs m);}//隐藏父类静态方法public static void s() {System.out.println(Bs s);}
}
public class OverrideDemo {public static void main(String[] args) {A o1 new B();o1.m(); // Bs mo1.s(); // As s((A)o1).m // Bs m被覆盖的父类实例方法不能再发现B o2 new B();o2.s // Bs s((A)o2).s // As s被隐藏的父类静态方法可以再发现}
}对于上面运行结果的解释是静态函数没有多态性函数入口地址在编译时确定编译时所有的变量都是按照其声明类型实例方法具有多态性在运行时时根据实际的运行时类型确定函数入口地址。