Java类
面向对象学习的三条主线:
- Java 类以及类成员:属性,方法,构造器,代码块,内部类
- 面向对象的特征:封装,继承, 多态, 抽象性
- 其他关键字:this, super static, final, abstract, interface, import, package…
注意事项:
- 同一个类中,在一个方法中,能调用属性(即全局变量),也可以调用同类中别的方法。【跟python一样】
- 方法中不能再定义一个新的方法
方法
方法的重载:
在同一个类中, 允许存在同名的方法, 只要参数个数或者参数类型不同即可。
跟返回值无关, 只跟参数个数或者参数类型有关。很多自带的包都是重载的, 很常见。
跟方法的修饰符, 返回值, 形参变量名无关。
特点:
两同一不同:同一个类名, 同一个方法名;参数列表不同;
重载跟方法体无关
示例代码:
package demo;
/*
*
* 方法重载
*
* */
public class demo_2 {
public static void main(String[] args) {
}
public void getSum(int i, int j){
System.out.println();
}
public void getSum(double i, int j){
System.out.println();
}
public void getSum(String i, int j){
System.out.println();
}
// 跟第一个getSum方法形成重载 方法名一致,参数列表不一致
public int getSum(String i, int j){
System.out.println();
return 0;
}
// 跟第一个getSum方法形成重载 方法名一致,修饰符不一致
private void getSum(String i, int j){
System.out.println();
}
}
可变形参
- 可变形参是参数的个数是变化的。
- 数据格式: 数据类型 … 参数名; 参数个数是0个1个或以上。
- 可变形参呀声明在末尾;
- 可变形参中定的形参, 指定某一个类型必须全为某一类型,String … i,那i必须全为字符型;
- 一个方法中,只能存一个形参; 不能多个;
- 可变形参方法和本类中的方法重名, 形参不同的方法之间构成重载;但是与参数类型相同的数组的方法不构成重载,二者不能共存。 【这点是历史问题】
示例代码:
package demo;
/*
* 可变形参
*
* */
public class demo_3 {
public static void main(String[] args) {
demo_3 d = new demo_3();
d.test(); // 输出 3
d.test(1); // 输出 1
d.test("asd"); // 输出 2
d.test("asd","qwr"); // 输出 3
}
public void test(int i){
System.out.println("1");
}
public void test(String i){
System.out.println("2");
}
public void test(String ... i){
// i 也就相当于一个数组,获取其中内容便利就行
System.out.println("3");
System.out.println(i); // 输出的是内存地址
for (int j = 0; j < i.length; j++) {
System.out.println(i[j]);
}
}
// String ... i 要放在后面
public void test(int a, String ... i){
System.out.println("4");
}
}
方法参数的值传递机制
变量的值传递机制
如果是基本数据类型,则赋值的是变量所保存的具体值;
如果是引用数据类型, 则赋值的是变量所保存的数据的地址值。
示例代码:
package demo;
public class demo_4 {
public static void main(String[] args) {
System.out.println("*****基本数据类型********");
int m = 10;
int n = m;
System.out.println("m = " + m + ", n = " + n);
n = 20;
System.out.println("m = " + m + ", n = " + n);
System.out.println("*****引用数据类型********");
Hello h1 = new Hello();
h1.orderId = 100;
Hello h2 = h1; // 赋值之后, h1 h2的地址值相同 指向同一个堆空间的对象实体。
System.out.println("h1地址:" + h1 + "h2地址:" + h2);
System.out.println(" h1.orderId = " + h1.orderId + ", h2.orderId = " + h2.orderId);
h2.orderId = 1000;
System.out.println("h1地址:" + h1 + "h2地址:" + h2);
System.out.println(" h1.orderId = " + h1.orderId + ", h2.orderId = " + h2.orderId);
}
}
class Hello{
int orderId;
}
输出结果:
基本数据类型*** m = 10, n = 10 m = 10, n = 20
引用数据类型***
h1地址:demo.Hello@61bbe9bah2地址:demo.Hello@61bbe9ba
h1.orderId = 100, h2.orderId = 100
h1地址:demo.Hello@61bbe9bah2地址:demo.Hello@61bbe9ba h1.orderId = 1000,
h2.orderId = 1000
形参的值传递机制
形参: 方法中的后面的参数部分
实参:方法调用的时候实际传递的,就是实参
如果***参数是基本数据类型,则实参赋给形参的是实参的实际数据值***;
参加下面的代码, 如果把交换的变量的代码放置在一个方法中,结果是不能交换成功的, 因为在swap方法中交换的是swap方法中的变量, 不是main方法中的变量。【参见示例代码1】
如果***参数是引用数据类型, 则实参赋给形参的是实参的存储数据的地址值***;
则将交换的代码放置在swap方法中,是能交换成功的。【参见示例代码2】
示例代码1 :
package demo;
public class demo_5 {
public static void main(String[] args) {
int m = 10;
int n = 20;
// 交换前的输出
System.out.println("m = " + m + ", n = " + n);
int temp = m;
m = n;
n = temp;
// 交换后的输出
System.out.println("m = " + m + ", n = " + n);
// 调用swap方法,进行交换, 但是并没有成功
demo_5 d = new demo_5();
d.swap(m, n);
System.out.println();
}
public void swap(int m, int n){
// swap方法中输出的是在栈中创建的swap中的m变量,n变量, 所以交换的是swap中的m n的值;
int temp = m;
m = n;
n = temp;
System.out.println("m = " + m + ", n = " + n);
}
}
输出结果:
m = 10, n = 20
m = 20, n = 10
m = 10, n = 20
示例代码2:
package demo;
public class demo_6 {
public static void main(String[] args) {
Date date = new Date();
date.m = 10;
date.n = 20;
// 交接前
System.out.println("交接前 date.m = " + date.m + " , date.n = " + date.n);
demo_6 dd = new demo_6();
dd.swap(date);
System.out.println("在swap方法之后 date.m = " + date.m + " , date.n = " + date.n);
}
public void swap(Date date1){
// 传递进来的date1是引用类型的地址, 是和前面的date一样的。,指向推空间同一个对象
int temp = date1.m;
date1.m = date1.n;
date1.n = temp;
System.out.println("在swap方法中 交接后 date.m = " + date1.m + " , date.n = " + date1.n);
}
}
class Date{
int m;
int n;
}
输出结果:
交接前 date.m = 10 , date.n = 20
在swap方法中 交接后 date.m = 20 , date.n = 10
在swap方法之后 date.m = 20 , date.n = 10
递归
(了解部分,暂时略过)
变量
属性也叫成员变量,与之相对应的是局部变量。
属性(成员变量) vs 局部变量
不同点
不同点 | 成员变量(属性) | 局部变量 |
---|---|---|
定义的位置不一样 | 写在类的一对 {} 之内 比如下面的 String name; int age; | 局部变量声明在方法内,方法形参处,代码块内,构造器形参,构造器内部的变量 |
权限修饰符不同 | 可以在声明属性的时候, 指明其权限修饰符,常用的权限修饰符 private public 缺省,protected | 局部变量 是不能加修饰符 |
默认初始化值不同 | 属性是有默认值的 | 局部变量没有默认值, 是必须得赋值的参见下面代码示例1 |
内存中加载的位置是不同的 | 属性加载到的堆中(非static) | 局部变量加载到栈中 |
相同点
- 都是变量
- 先声明后使用
- 都有其作用域
public void talk(String language){ // 此处的 String language 是形参, 是局部变量
// 这里的局部属性是不能加权限修饰符的
String food = "馒头"; // 方法内的也是局部变量
System.out.println("hello " + language);
System.out.println("我喜欢吃 " + food);
int age; // 如果只是赋值并没有使用, 是不会报错的
System.out.println(age); // 这样写会出错 没有初始化
// Variable 'age' might not have been initialized 会显示这样错误
// 需要像上面food一样赋值才能用
}