Java基础-面向对象(一)
一、类和对象
类是对一类事物的描述,是抽象的、概念上的定义
对象时实际存在的该类事物的每一个个体,也称为实例
二、类的成员
- 属性:类中的成员变量
- 行为:类中的成员方法
- 构造器
- 代码块
- 内部类
三、类和对象的创建
1. 使用步骤
- 创建类:设计类的成员
- 创建类的对象
- 通过
对象.属性
或对象.方法
调用对象的结构
package com.example.www;
public class PersonTest {
public static void main(String[] args) {
// 创建Person类的对象(实例化一个类)
Person p1 = new Person();
// 调用对象的属性 对象.属性
p1.name = "Tom";
System.out.println(p1.name);
// 调用对象的方法 对象.方法
p1.eat();
p1.talk("Chinese");
}
}
// 类的创建
class Person {
// 属性
String name;
int age;
// 方法
public void eat(){
System.out.println("eat...");
}
public void talk(String language){
System.out.println(language);
}
}
如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的)。
2. 匿名对象
-
创建的对象没有显式的赋值给一个变量
-
只能调用一次
public class PhoneTest {
public static void main(String[] args) {
new Phone().sendMsg();
new Phone().playGame();
// 这个两个不同的对象
}
}
class Phone{
public void sendMsg(){
System.out.println("发短信");
}
public void playGame(){
System.out.println("玩游戏");
}
}
四、属性
属性和局部变量的区别:
相同点:
- 定义变量的格式:
数据类型 变量名 = 变量值
- 先声明后使用
- 变量都有其对应的作用域
不同点:
- 在类中声明的位置不同
- 属性:直接定义在类的一对
{}
内 - 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
- 属性:直接定义在类的一对
- 关于权限修饰符的不同
- 属性:可以在声明属性时,指明其权限。常用的权限修饰符:private、public、缺省、protected。
- 局部变量:不可以使用权限修饰符。
- 默认初始化值
- 属性:根据其类型,都有默认初始化值
- 局部变量:没有默认初始化值,在调用局部变量之前一定要显式赋值。
- 在内存中加载的位置
- 属性:加载到堆空间中(非static)
- 局部变量:加载到栈空间中
五、方法
方法:描述类应该具有的功能。
1. 方法的声明
权限修饰符 返回值类型 方法名(形参列表){
方法体;
}
- 权限修饰符(4种):private、public、缺省、protected
- 返回值
- 如果方法有返回值,则必须在方法声明时指定返回值类型,同时方法中需要使用
return
关键字来返回指定类型的变量或常量。 - 如果方法没有返回值,则方法声明时使用
void
来表示。通常在没有返回值的方法中,就不能使用return
关键字,如果使用的话只能使用return;
来表示此方法结束。
- 如果方法有返回值,则必须在方法声明时指定返回值类型,同时方法中需要使用
- 方法名:属于标识符,遵循标识符的规则和规范。
- 形参列表:方法可以声明0个、1个或多个形参。
数据类型1 形参1, 数据类型2 形参2...
- 方法体:方法功能的实现
2.return
关键字
- 使用范围:使用在方法体中
- 作用:
- 结束方法
- 针对于有返回值类型的方法,使用
return 数据
返回所要的数据。
- return关键字后面不可以声明执行语句
3. 方法的使用
- 方法在使用中,可以调用当前类的属性或方法
- 方法中不能定义方法
4. 方法重载
在一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
与返回值类型无关,只看参数列表,且参数列表必须不同,调用时,根据方法参数列表的不同来区别。
判断方法是否重载,和方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系。
5. 可变个数的形参
允许直接定义能和多个实参向匹配的形参,从而可以用一种更简单的方式来传递个数可变的实参。
格式:数据类型 ... 变量名
当调用可变个数形参的方法时,传入的参数个数可以是0个,1个或多个。
可变个数形参的方法与本类中方法名相同、形参不同的方法之间构成重载。
可变个数形参在方法的形参中,必须声明在末尾。
可变个数形参在方法的形参中,最多只能声明一个可变形参。
public class MethodArgsTest {
public static void main(String[] args) {
MethodArgsTest test = new MethodArgsTest();
test.show("Hello");
test.show("Hello", "World");
// test.show(new String[]{"Hello", "World"});
}
// public void show(String[] strs) {
public void show(String ... strs){
System.out.println(strs);
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
}
}
6. 方法参数的值传递机制
Java中方法的参数传递方式只有一种:值传递。即将实际参数值的副本传入方法内,而参数本身不受影响。
- 形参是基本数据类型,将实参基本数据类型变量的"数据值"传递给形参
- 形参是引用数据类型,将实参引用数据类型变量的"地址值"传递给形参
6.1 方法中变量的赋值:
-
如果变量是基本数据类型,此时赋值的是变量所保存的数据值
-
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
public class ValueTransferTest {
public static void main(String[] args) {
int m = 10;
int n = m;
System.out.println("m = " + m + ", n = " + n); // m = 10, n = 10
n = 20;
System.out.println("m = " + m + ", n = " + n); // m = 10, n = 20
User user1 = new User();
user1.name = "Tom";
User user2 = user1; // user1和user2的地址值相同
System.out.println("user1.name = " + user1.name + ", user2.name = " + user2.name); // user1.name = Tom, user2.name = Tom
user2.name = "Jerry";
System.out.println("user1.name = " + user1.name + ", user2.name = " + user2.name); // user1.name = Jerry, user2.name = Jerry
}
}
class User{
String name;
}
6.2 方法的形参值传递机制
- 形参:方法定义时,声明在小括号内的参数
- 实参:方法调用时实际传递给形参的值。
值传递机制
- 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
- 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
例:参数是基本数据类型
public class ValueTransferTest {
public static void main(String[] args) {
int m = 10;
int n = 20;
ValueTransferTest test = new ValueTransferTest();
test.swap(m, n);
System.out.println("m = " + m + ", n = " + n); // m = 10, n = 20
}
public void swap(int m, int n){
int tmp = m;
m = n;
n = tmp;
}
}
例:参数是引用数据类型
public class ValueTransferTest {
public static void main(String[] args) {
Data data = new Data();
data.m = 10;
data.n = 20;
ValueTransferTest test = new ValueTransferTest();
test.swap(data);
System.out.println("m = " + data.m + ", n = " + data.n); // m = 20, n = 10
}
public void swap(Data data){
int tmp = data.m;
data.m = data.n;
data.n = tmp;
}
}
class Data{
int m;
int n;
}
7. 递归
1. 递归求和
public class RecursionTest {
public static void main(String[] args) {
int sum = new RecursionTest().getSum(100);
System.out.println(sum);
}
public int getSum(int n) {
if (n == 1){
return 1;
}else{
return n + getSum(n-1);
}
}
}
2. 斐波那契数列
public class FibonacciTest {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
long num = fibanacci(i);
System.out.print(num + " ");
}
}
public static long fibanacci(long number) {
if (number == 0 || number == 1){
return number;
}else{
return fibanacci(number -1 ) + fibanacci(number - 2);
}
}
}
3. 汉诺塔
// https://blog.csdn.net/ljmingcom304/article/details/50296939
public class HanoiTower {
public static void hanoi(int n, String a, String b,String c) {
if (n == 1) {
// 只有一个圆盘时直接从A石柱移动到C石柱
move(n, a, c);
} else {
// 将前n-1个圆盘从石柱A移动到石柱B
hanoi(n - 1, a, c, b);
// 将第n号圆盘从石柱A移动到石柱C
move(n, a, c);
// 将前n-1个圆盘从石柱B移动到石柱C
hanoi(n - 1, b, a, c);
}
}
public static void move(int n, String i, String j) {
System.out.println("第" + n + "个圆盘," + "从" + i + "移动到" + j);
}
public static void main(String[] args) {
hanoi(3,"A","B","C");
}
}