面向对象编程(基础)
类与对象
类 :代表的是一种数据类型,可以是自己定义的,也可以是Java提供的,例如 int 等。
对象 :指的是具体的实例
类是广泛的 ,对象是类创造出的具体的实物,比如int中有 整数 100、200 这一些
如果学过结构体,就可能可以更加清晰的体会,看下面的代码可以加深认知。
类与对象的区别和联系
1. 类是抽象的,概念的,代表某一事物,例如 人,猫...即它是数据类型
2. 对象是具体的,实际的,代表一个具体事物,即实例
3. 类是对象的模板,对象是类的一个 个体,对应着实例
import java.util.Scanner;
/**
* 创建一个猫类
*/
class Cat {
//属性/成员变量
String name; //名字
int age; //年龄
String color;// 颜色
}
public class Hello {
public static void main(String[] args) {
/**
* 1.new Cat() 创建一只猫
* 2.Cat cat1 = new Cat(); 把创建的猫赋给 cat1
* 3.cat1 就是一个对象
*/
Cat cat1 = new Cat();
cat1.age = 17;
cat1.color = "red";
cat1.name = "kate";
System.out.println("猫的信息" + "名字 "+cat1.name + "颜色 " + cat1.color + "年龄 "+ cat1.age);
}
}
对象在内存中存在的形式
* 字符串 放在方法区中的常量池
* 整形 放在堆中
属性/成员变量
1. 从概念或叫法上:成员变量 = 属性 = field(字段)
2. 属性是类的一个组成部分,一般是基本数据类型,也可以是引用类型(对象,数组)
注意事项和细节说明
1. 属性的定义语法同变量,例 访问修饰符,属性类型,属性名;
1. 访问修饰符:控制属性的访问范围 。四种访问修饰符 :public,proctected,private,默认
2. 属性的定义类型可以为任意类型,包含基本类型或引用类型
3. 属性如果不赋值,有默认值,规则和数组一致
Java内存的结构分析
* 栈:一般存放基本数据类型(局部变量)
* 堆:存放对象
* 方法区:常量池,类加载信息
* 示意图
成员方法
简称 方法
public class Hello {
public static void main(String[] args) {
/**
* 1.方法写好后,不去调用,没有输出
*/
Person person = new Person();
person.speak();
person.cal01();
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
person.cal02(n);
System.out.println(person.getSum(n,n));
}
}
class Person{
String name;
int age;
/**
* 方法 (成员方法)
* 添加speak 成员方法,输出我是一个人
* 1.public 表示方法是公开
* 2.void : 表示方法是没有返回值的
* 3.speak() : speak是方法名,() 形参列表
*/
public void speak(){
System.out.println("我是一个人");
}
public void cal01(){
int sum = (1+1000)*500;
System.out.println(sum);
}
public void cal02(int n){
int sum = (1+n)*n/2;
System.out.println(sum);
}
public int getSum(int x, int y){
return x+y;
}
}
方法调用
1.当程序执行到方法时,就会开辟一个独立的空间(栈空间)
2.当方法执行完毕,或者执行到return语句时,就会返回
3.返回到调用方法的地方
4.返回后,继续执行方法后面的代码
成员方法的定义
public 返回数据类型 方法名 (参数列表..){ //方法体
语句;
return 返回值;
}
1.参数列表:表示成员方法输入 cal(int n)
2.数据类型 (返回类型) : 表示成员方法输出 ,void 表示没有返回值
3.方法主体:表示为了实现某一功能代码块
4.return 语句不是必须的
返回数据类型
* 一个方法最多有一个返回值
* 返回的类型可以为任意类型,包含基本类型或引用类型
* 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为return 值;
而且要求返回值类型必须和return的值类型一致或兼容
* 如果方法是void,则方法体中可以没有return语句,或者只写return
形参列表
* 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开
* 参数类型可以为任意类型,包含基本类型或引用类型
* 调用带参数的方法,一定对应着参数列表传入相同类型或兼容类型的参数
* 方法定义时的参数称为形式参数,简称形参;方法调用时的参数成为实际参数,简称实参,实参和形参的类型要一定一致或者兼容,个数、顺序必须要一致!
方法调用
* 同一个类中的方法调用:直接调用即可
* 跨类中的方法A类调用B类方法:需要通过对象名调用。
* 跨类的方法调用和方法的访问修饰符相关
class A{
// 同一个类中的方法调用:直接调用即可
public void Print(int n){
System.out.println("nice" + n);
}
public void sayOk(){//sayOk 调用 print (直接调用)
Print(10);
}
//* 跨类中的方法A类调用B类方法:需要通过对象名调用。
public void m1(){
//创建B类对象,如何在调用方法即可
B b = new B();
b.hi();
}
}
class B{
public void hi(){
System.out.println("B类中的hi()被执行");
}
}
成员方法传参机制
基本数据类型,传递的是值(值拷贝),形参的任何形式改变不影响实参!
引用类型传递的是地址,(传递也是值,但是值是地址) ,可以通过形参影响实参!
编写一个方法copyPerson,复制一个Person对象,返回复制对象
/**
* 编写一个方法copyPerson,复制一个Person对象,返回复制对象
*public class Hello {
public static void main(String[] args) {
Person person = new Person();
person.name="zhangshan";
person.age=17;
MyTools myTools = new MyTools();
Person p = myTools.copyPerson(person);
// 这里 p 和 person 俩个属于独立的对象,内容一样
}
}/
class MyTools{
/**
* 1.先确定返回的类型
* 2.确定方法名称和传参
* 3.确定构造方法
* @param p
* @return
*/
public Person copyPerson(Person p){
Person p2 = new Person();
p2.name = p.name;
p2.age = p.age;
return p2;
}
}
方法递归调用
递归就调用自己,每次调用的值不一样,解决复杂的问题,同时代码简洁
递归规则
1. 执行一个方法时,就创建一个新的受保护的独立空间
2. 方法的局部变量是独立的,不会互相影响
3. 如果方法中使用的是引用类型变量,就会共享引用类型的数据
4. 递归必须向退出的条件逼近,否则会出现死循环
5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
汉诺塔
class Hanoi{
public void tools(int num , char A, char B , char C){
if(num == 1){
System.out.println(A + "->" + C);
}else{
// 把底盘移动到C,借助C塔,其他盘移动到A塔
tools(num-1,A,C,B);
System.out.println(A + "->" + C);
// 借助A塔,把B塔上的盘子移动到C
tools(num-1,B,A,C);
}
}
}
方法重载
Java中允许同一个类中,多个同名方法的存在,但要求的形参不一致!
重载的好处:减轻了起名的麻烦,减轻了记名的麻烦
注意事项:
* 方法名 : 必须相同
* 形参列表:必须不同(形参类型 或 个数 或 顺序)
* 返回类型:无要求
可变参数
Java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。就可以通过可变参数实现
注意事项和使用细节
* 可变参数数量可以时任意个
* 可变参数的实参可以为数组
* 可变参数的本质就是数组
* 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
* 一个形参列表只能出现一个可变参数
class HspMethod{
/**
* 计算2,3,4个数的和
*/
public int sum(int n1, int n2){
return n1+n2;
}
public int sum(int n1, int n2,int n3){
return n1+n2+n3;
}
/**
* 上面方法名称相同,功能相同,参数的个数不同
* 1.int...表示接受的时可变参数,类型是int,即可以接受多个int
* 2.使用可变参数时,可以当作数组来使用
* 3.遍历求和
*/
public int sum(int... nums){
int res = 0;
for(int i = 0; i < nums.length ; i++){
res += nums[i];
}
return res;
}
}
作用域
1. 在Java编程中,主要的变量就是属性(成员变量) 和 局部变量
2. 一般说的局部变量指的是成员方法中定义的变量
3. Java中作用域的分类全局变量:也就是属性,作用域为整个类体Cat类:cry eat 等方法使用属性局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中
4. 全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
注意事项和细节
1. 属性和局部变量可以重名,访问时遵守就近原则
2. 在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名
3. 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的死亡而死亡。局部变量,生命周期较短,伴随着它的代码的执行而创建,伴随着代码块的结束而死亡,即在一次方法调用过程中。
4. 作用域范围不同
全局变量/属性:可以被本类使用,或者其他类使用(通过对象调用)
局部变量:只能在本类中对应的方法中使用
5.修饰符不同
全局变量/属性可以加修饰符
局部变量不可以加修饰符
构造方法/构造器
基本语法
[修饰符] 方法名(形参列表){
方法体;
}
1. 构造器的修饰符 可以默认
2. 构造器没有返回值
3. 方法名 和 类名字必须一样
4. 参数列表 和 成员方法一样的规则
5. 构造器的调用,由系统完成
细节事项和使用细节
1. 一个类可以定义多个不同的构造器,即构造器重载
2. 构造器名和类名要相同
3. 构造器没有返回值
4. 构造器是完成对象的初始化,并不是创建对象
5. 在创建对象时,系统自动的调用该类的构造方法
6. 如果没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造方法)
7. 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能使用默认构造器,除非显式的定义一下。
public class Hello {
public static void main(String[] args) {
// 当new 一个对象时,直接通过构造器指定名字和年龄
Person1 p1 = new Person1("zhangsan",18);
}
}
class Person1{
String name;
int age;
/**
* 1.构造器没有返回值,也不能写void
* 2.构造器的名称和类Person1一样
* 3.(String pName, int pAge) 就是构造器形参列表,规则和成员方法一样
* @param pName
* @param pAge
*/
public Person1(String pName, int pAge){
name = pName;
age = pAge;
}
}
流程分析
1. 加载Person类信息,只会加载一次
2. 在堆中分配空间(地址)
3. 完成对象初始化
this关键字
this指的是对象,谁在创建新的对象,this指的就是哪个对象
注意事项:
1. this关键字可以用来访问本类的属性、方法、构造器
2. this用于区分当前类的属性和局部变量
3. 访问成员方法的语法:this.方法名(参数列表)
4. 访问构造器语法: this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另一个构造器)
5. this不能在类定义的外部使用,只能在类定义的方法中使用