方法和类详解
- 控制类成员函数的访问
- 向方法传递对象
- 返回对象
- 方法重载
- 重载构造函数
- 递归
- static关键字
- static代码块
- 嵌套类和内部类
- varargs(可变长度实参)
控制类成员函数的访问
Java中的访问控制符有三个:
- public:共有访问控制符。允许程序中的其他代码任意访问类的成员(默认的访问设置,也就是没有使用访问修饰符)
- private:私有访问控制符。只有该类的其他成员可以访问该成员。
- protect:保护访问控制符。在继承中会体现出其功能。
向方法传递对象
在之前使用过简单类型作为形参传递给方法,而对象作为复合数据类型,也能够向方法传递形参。
//PassOb.java
public class PassOb {
public static void main(String[] args) {
Block aBlock = new Block(1);
Block bBlock = new Block(1);
if (aBlock.isSame(bBlock)) {
System.out.println("true");
}
else {
System.out.println("false");
}
}
}
class Block{
int a;
Block(int a) {
this.a = a;
}
boolean isSame(Block a) { //向方法传递对象
if(a.a == this.a)
return true;
else {
return false;
}
}
}
输出结果如下:
true
在Java中传递实参有两种方法:
- 传值调用:顾名思义,传值调用,只是给实参的数值进行赋值等操作,而不改变原本实参的传递方法。向方法传递基本类型时,将使用传值调用。
- 引用调用:通过引用把实参传递给形参等其他参数,改变其数值将会影响实参的数值。向方法传递对象时,将使用引用调用。
//testPass_one.java
//传值调用
public class testPass_one {
public static void main(String[] args) {
test_one t = new test_one();
int a = 1, b = 2;
System.out.println("a = " + a + " b = " + b);
t.change(a, b);
System.out.println("a = " + a + " b = " + b);
}
}
class test_one{
public void change(int a, int b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
}
输出结果如下:
a = 1 b = 2
a = 1 b = 2
//testPass_two.java
//引用调用
public class testPass_two {
public static void main(String[] args) {
test_two a = new test_two(1, 2);
System.out.println("a = " + a.a + " b = " + a.b);
a.change(a);
System.out.println("a = " + a.a + " b = " + a.b);
}
}
class test_two{
int a, b;
public test_two(int a, int b) {
this.a = a;
this.b = b;
}
public void change(test_two t) {
int tmp;
tmp = t.a;
t.a = t.b;
t.b = tmp;
}
}
输出结果如下:
a = 1 b = 2
a = 2 b = 1
这里还有对Java中的数组引用赋值的说明。
当对象引用被传递给方法时,引用本身是使用传值调用方式进行传递的。然而被传递的值引用了一个对象,所以该值的副本依然引用了被相应实参引用的同一个对象。
返回对象
对象在Java中也能够被返回,其方法与返回基本类型相似。只是其类型符改成对象的类型符,return 后改成对象即可。
方法重载
方法重载:在Java中,同一个类中的两个或多个方法可以共享一个名称,只要它们的形参声明不一样即可。
方法重载是Java实现多态性的途径之一。
方法重载的要求:每个被重载的方法的形参类型和数量必须不同,两个方法仅返回类型不同无法构成重载。
在方法中的自动转换只能在形参与实参之间不能直接匹配时使用。
签名:指的是方法名及其形参列表。(不包括返回类型)
重载构造函数
与方法一样,构造函数同样能被重载,其形式与方法类似。
最常见的重载构造函数的原因是使用一个对象去初始化另一个对象。(此时是只传值,不引用)
//SumDemo.java
public class SumDemo {
public static void main(String[] args) {
Summation s1 = new Summation(5);
Summation s2 = new Summation(s1);
s2.sum = 10;
System.out.println("s1.sum = " + s1.sum);
System.out.println("s2.sum = " + s2.sum);
}
}
class Summation{
int sum;
Summation(int num){
sum = 0;
for (int i = 1; i <= num; i++) {
sum += i;
}
}
Summation(Summation ob){
sum = ob.sum;
}
}
输出结果如下:
s1.sum = 15
s2.sum = 10
递归
在Java中,调用自己的方法称为递归方法。
递归的典型例子就是求阶乘或连续数的和。
//Recursion.java
public class Recursion {
public static void main(String[] args) {
factR aFactR = new factR();
System.out.println("1 + 2 + ... + 100 = " + aFactR.sum(100));
}
}
class factR{
int sum(int n) {
if(n == 1)
return 1;
else {
return sum(n - 1) + n;
}
}
}
输出结果如下:
1 + 2 + … + 100 = 5050
static关键字
如果想要创建一个与任何对象无关的类成员,则应该在它的声明之前添加关键字static,当一个成员被声明为static之后,可以在创建类的对象之前访问该成员,而无需引用任何对象。
//StaticDemo.java
public class StaticDemo {
public static void main(String[] args) {
Static aStatic = new Static();
Static bStatic = new Static();
System.out.println("aStatic.a = " + aStatic.a);
System.out.println("aStatic.b = " + aStatic.b);
System.out.println("bStatic.a = " + bStatic.a);
System.out.println("bStatic.b = " + bStatic.b);
aStatic.a = 1;
aStatic.b = 10;
System.out.println("aStatic.a = " + aStatic.a);
System.out.println("aStatic.b = " + aStatic.b);
System.out.println("bStatic.a = " + bStatic.a);
System.out.println("bStatic.b = " + bStatic.b);
}
}
class Static{
int a = 4;
static int b = 1;
}
输出结果如下:
aStatic.a = 4
aStatic.b = 1
bStatic.a = 4
bStatic.b = 1
aStatic.a = 1
aStatic.b = 10
bStatic.a = 4
bStatic.b = 10
这个程序是没有问题,但是在eclipse中会有提示“The static field Static.b should be accessed in a static way”,也就是说b已经定义成了static方式,所有可以对其进行改进
//StaticDemo.java
public class StaticDemo {
public static void main(String[] args) {
Static aStatic = new Static();
Static bStatic = new Static();
System.out.println("aStatic.a = " + aStatic.a);
System.out.println("aStatic.b = " + Static.b);
System.out.println("bStatic.a = " + bStatic.a);
System.out.println("bStatic.b = " + Static.b);
aStatic.a = 1;
Static.b = 10;
System.out.println("aStatic.a = " + aStatic.a);
System.out.println("aStatic.b = " + Static.b);
System.out.println("bStatic.a = " + bStatic.a);
System.out.println("bStatic.b = " + Static.b);
}
}
class Static{
int a = 4;
static int b = 1;
}
运行结果丝毫不变
static代码块
有的时候需要在创建对象之前,进行初始化,例如,可能需要建立与远程站点的连接。此时将可以使用static代码块,在类之前执行。
//StaticDemo.java
public class StaticDemo {
public static void main(String[] args) {
Static aStatic = new Static();
Static bStatic = new Static();
System.out.println("aStatic.a = " + aStatic.a);
System.out.println("aStatic.b = " + Static.b);
System.out.println("bStatic.a = " + bStatic.a);
System.out.println("bStatic.b = " + Static.b);
aStatic.a = 1;
Static.b = 10;
System.out.println("aStatic.a = " + aStatic.a);
System.out.println("aStatic.b = " + Static.b);
System.out.println("bStatic.a = " + bStatic.a);
System.out.println("bStatic.b = " + Static.b);
}
}
class Static{
static {
System.out.println("Inside static block.");
}
public Static() {
System.out.println("Set Static.");
}
int a = 4;
static int b = 1;
}
输出结果如下:
Inside static block.
Set Static.
Set Static.
aStatic.a = 4
aStatic.b = 1
bStatic.a = 4
bStatic.b = 1
aStatic.a = 1
aStatic.b = 10
bStatic.a = 4
bStatic.b = 10
嵌套类和内部类
不带static修饰符
嵌套类
内部类
嵌套类的作用域仅局限于它的外层类。
内部类是不带static修饰符的嵌套类,它有权访问其外层类的所有变量和方法。
varargs(可变长度实参)
varargs方法的形参列表的长度可变,数量不固定,因此,varargs方法可以接受可变数量的实参。
可变长度实参由三个句号指定(…)
//VarargsDemo.java
public class VarargsDemo {
static void vaTest(int ...v) {
System.out.println("Number of args: " + v.length);
System.out.println("Contents:");
for(int i = 0; i < v.length; ++i) {
System.out.println(" args " + i + ":" + v[i]);
System.out.println();
}
}
public static void main(String[] args) {
vaTest(10);
vaTest(1, 2, 3);
vaTest();
}
}
输出结果如下:
Number of args: 1
Contents:
args 0:10Number of args: 3
Contents:
args 0:1args 1:2
args 2:3
Number of args: 0
Contents:
在使用varargs方法时,容易产生歧义,如当无参数的时候,并且重载了varargs方法,此时就出现了歧义,因此有时需要放弃重载,改用两个不同的方法名。