前言:
- 引出类与对象(oop) -- 为什么需要类与对象(oop)
- 例:我有两只小狗,有姓名,年龄,性别,怎么完成该操作?
//用变量 String DogName = \"小白\"; int DogAge = 6; char DogSex= \'公\' String DogName = \"小新\"; int DogAge = 6; char DogSex= \'公\' //用数组 String[] Dog = {\"小白\",\"6\",\"公\"}; //数字类型不明确 String[] Dog = {\"小新\",\"6\",\"公\"}; //数字类型不明确
- 上面案例中完成了小狗的属性创建,那么现在我想给小狗添加一个爱好怎么办?是不是特别麻烦,如果是100只小狗呢?
类与对象是什么:
- 看前言已经知道,用变量和数组创建一个猫是多么的麻烦,增加一个属性就需要重复大量代码
- 类:如猫类 -> 把所有猫的属性和行为提取到该猫类中形成一个类
- 猫类:是自定义的数据类型,如int就是java提供的数据类型
- 对象:如猫类 -> 提供猫类去创建出来的就是对象,猫对象
快速入门:
- 看下面代码就可知道和原本的变量和数组好处在哪,属性类型明确,添加属性值方便,开发效率高
public static void main(String[] args) { Cat cat1 = new Cat();//创建第一个猫对象 cat1.name = \"小白\";//给属性赋值 cat1.age = 10; System.out.println(cat1.name +\" \"+ cat1.age);//输出属性值 Cat cat2 = new Cat();//创建第二个猫对象 cat2.name = \"小新\";//给属性赋值 cat2.age = 20; System.out.println(cat2.name +\" \"+ cat2.age); } } class Cat{//定义一个猫类 String name;//属性 int age; }
-
类属性的不同叫法和细节:
Class Cat{ String name; // 可以叫 1.属性 2.成员变量 3.字段 int[] age; // 可以放所有基本数据类型和引用类型 doeble money; } pring(car.name+\" \"+car.age...)//直接输出属性,会输出属性默认值 //int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \\u0000, //boolean false,String null
-
对象内存布图:
类和对象的内存分配机制:
-
java内存结构分析:
- 栈:一般存放基本数据类型(局部变量)
- 堆:一般存放对象或数组
- 方法区:一般存放常量池和类加载信息
-
java创建对象流程简单分析:
- 创建对象然后在方法区加载类信息 -- (只是加载一次,不会创建一个对象加载一次)
- 在堆中创建空间,进行默认初始化
- 把栈地址指向对象
- 进行初始化如:cat,pag = 10; cat.name = \"小白\"
成员方法:
- 什么是成员方法?就是在类在写一个方法(方法是基础里的知识),和写一个属性是一样的
- 为什么需要成员方法?:
- 循环遍历一个数组 是否需要写代码遍历循环,
- 在遍历一个数组呢,复制粘贴代码在循环一次?那我要改动遍历代码,所有的复制粘贴代码都要改?
- 解决问题:所以只需要通过调用成员方法,就可以减少代码的复用
-
快速入门:
public static void main(String[] args) { Cat cat = new Cat(); cat.show();//调用方法 } } class Cat{ String name = \"小白\"; /* public 公共的 -- 作用域(当然还有其它的) void -- 表示方法没有返回值 int -- 表示方法返回值,基本数据类型,引用类型都可以 return -- 表示把值返回 show-- 方法名 () -- 形参列表,表示可以接收形参 {} -- 方法体 */ public void show(){ //方法体 System.out.println(\"我叫\"+name); }
//有参返回 public int show2(int i, int n ){ return i+n; } }
-
方法调用机制:
-
方法的定义:
访问修饰符 返回数据类型 方法名(形参列表..) {//方法体 语句; return 返回值; //如果是viod就需要该存在了
}
-
成员方法的下细节:
- 一个方法最多一个返回值(但是可以有多个返回结果,返回数组形式)
- 可以返回任意类型,基本数据类引用类型(数组,对象)
- 如果方法是void,不需要写return,或者只写return(不能用返回值)
- 返回值类型return必须和返回值统一或者兼容,如:需要返回值是double,return可以返回int,反过来就不可以需要数据类型可以转换
- 遵循驼峰命名法
class Dog{ //1.返回多个结果 public int[] king(){ int[] sum = new int[3]; sum[0] = 1; sum[1] = 2; return sum; //返回多个结果 } //2.void可以写return,但不能有返回值 public void king2(){ pring(\"加油\"); return; } //3.可以返回兼容的类型 public double king3(){ int i = 99; return i ; } }
-
成员方法 - 形参列表细节:
- 一个方法可以有0个参数,也可以有多个参数有逗号隔开
- 参数类型可以是任意类型,基本数据类型或引用类型
- 调用参数方法时,传入的参数一定是相同的类型或兼容的类型
- 方法定义时的参数叫形参(形式参数),调用方法时传入的叫实参,实参和形参必须统一或兼容
//一个方法可以有0个参数,也可以有多个参数有逗号隔开 public int show(int num1, int num2){ return num1+num2; } //参数类型可以是任意类型,基本数据类型或引用类型 public int[][] show2(int[][] map){ int[][] nums = new int[11][11]; return nums; }
-
成员方法 - 方法体细节:
- 方法体中不能嵌套方法
-
成员方法 - 方法调用细节:
- 同类中可以直接调用同类中的其它方法
- 在方法中可以通过对象调用其它类中的方法 - 这里注意因为跨类调用还需要考虑访问修饰符
class A{ public void print(){ System.out.println(\"我在同类中的其它方法调用了\"); } //同类中可以直接调用其它方法 public void sayOK(){ print(); System.out.println(\"我调用了print()方法\"); } //在方法中可以,通过对象调用其它类方法 public void m1(){ System.out.println(\"A的m1被调用\"); new B().hi(); System.out.println(\"A的m1现在执行 \"); } } class B{ public void hi(){ System.out.println(\"我是B类的hi()方法\"); } }
-
成员方法 - 基本数据类型传递机制
- 基本数据类型传递的是值拷贝,形成不会改变实参
-
成员方法 - 引用类型传递机制
- 引用类型传递的是地址 - 会对引用类型改变
- 如果在方法中改变了传递过去的地址,改变了地址或指空,那么对引用类型不会进行影响
方法的重载:
- 什么是重载?-> 同一个类中,多个方法名称一样的方法存在,但是形成列表不一致
- 重载的好处 -> 如我的方法是显示加法后的结果,那可以是int加int,doblue加int,那么可以通过同一方法名来实现,只需要传递不同的参数
class AA{ public void show(int i ,int n){ System.out.println(i+n); } public void show(int i ,double n){ System.out.println(i+n); } public void show(double i ,double n){ System.out.println(i+n); } public void show(double i, int n){ System.out.println(i+n); } }
-
重载细节:
- 方法名必须相同
- 形成列表不能一致
- 可以是任意返回类型(如:可以返回int double void Cat 数组类型 等)
//返回形成列表不能一致,返回类型不同也不行 public void show(double i ,double n){ System.out.println(i+n); } public double show(double i ,double n){ System.out.println(i+n); }
可变参数:
- 什么是可变参数?就是可以传递零个或多个数
- 使用可变参数,可以当数组使用
- 语法:int... sum -- 就是int类型的可变参数
public int sum(int... nums){ int res = 0; for (int i = 0; i < nums.length; i++) { res += nums[i]; } return res; }
-
可变参数 - 细节:
- 可变参数实参可以是0个或多个
- 可变参数的实参可以是数组
- 可变参数本质就是数组
- 可以参数可以和普通类型参数一起放在形成列表中,可变参数必须放在普通参数后面
- 一个形成列表,只能出现一个可变参数
public class Test { public static void main(String[] args) { AA aa = new AA(); //可变参数的实参可以是数组 int[] num = {1,2,3}; int sum = aa.sum(num); } } class AA{ public int sum(int... nums){ int res = 0; for (int i = 0; i < nums.length; i++) { res += nums[i]; } return res; }
//可以参数可以和普通类型参数一起放在形成列表中,可变参数必须要在普通类型参数后面 public void sum(String name,int... nums){ };
//一个形成列表只能出现一个可变参数 //public void sum(double... num,int... nums){};//错误 }
作用域:
- 什么是作用域?就是属性在该类中的使用范围
- 作用域一般访问:全局变量和局部变量
- 全局变量:在该类中都可以使用
- 局部变量:只能在自己的一亩三分地使用,在自己的代码块中使用
//快速入门 class AA{ //该属性在AA类中都可以访问 String name = \"king\"; //成员变量/属性/全局变量 public void show(){ //成员方法 //该属性只能在show()方法中使用 char sex = \'男\'; //局部变量 } }
-
作用域细节:
- 全局变量(属性)有默认值;局部变量没有默认值(定义时必须赋值)
- 全局变量(属性)和局部变量名字可以重复,访问时就近原则,靠我近访问谁
- 全局变量(属性)可以使用访问修饰符,局部变量不可以
- 全局变量(属性)伴随着对象的销毁而销毁,局部变量是代码块的销毁而销毁
- 通俗易懂版:new一个对象,该对象不销毁全局变量还在,局部变量一般中方法中,如方法结束局部变量就销毁
class AA{ //1.属性默认值:String是null String name; //2.属性和局部变量名字可以一致,就近原则访问 int age; //3.属性可以使用访问修饰符 public char sex; public void show(){ //1.局部变量:没有默认值,不写就错 char sex = \'男\'; //2.属性和局部变量名字可以一致,就近原则访问 int age = 18; } }
构造器:
- 什么是构造器?完成对新对象的初始化
- 理解:调用构造器时,对象已存在内存中,调用构造器去完成对象属性的的初始化
- 在理解:等于AA类中有 String name; 我的操作等于 String name = \"小白\";
- 语法:【修饰符】类名 (形参列表) {代码块}
class AA{ String name; int age; public AA(String name,int age){ System.out.println(\"name+age\"); name = name; age = age; } }
-
构造器 - 细节:
- 可以构造器的重载
- 控制器没有返回值
- 控制器名和类名相同
- 构造器完成对象的初始化,不是创建对象
- 类中没有定义构造器,系统默认是给一个默认的无参构造器
- 定义了自定义的构造器后,默认的构造器就会被覆盖,需要重新定义才能使用
对象创建的流程+构造器版本:
- 类加载
- 在堆在分配空间 == 空对象
- 对象初始化 - 属性先赋值(默认值先赋值,在到定义值,在到构造器)
- 栈中接收堆中地址
this关键字:
- 什么是this?我直接调用我自己
- 为什么要使用this?如:构造器中形参为 name 类属性 name 我要name = name怎么办?是不是太含糊不清,谁是谁的name
- 案例说明什么是,我直接调用我自己:
public class Test { public static void main(String[] args) { AA aa = new AA(\"小白\",20); //1.调用该方法name = null,age = 0 aa.show(); } } class AA{ String name; int age; public AA(String name, int age) { //2.因为:这里把name当成了局部变量 //自己 给 自己 赋值肯定是错误的 name = name; age = age; //3.this.name表示当前对象的name属性 //当前对象是谁?AA aa = new AA(\"小白\",20); //所以说是:我自己调用我自己 this.name = name; this.age = age; } public void show(){ System.out.println(name+\" \"+age); } }
-
深入了解,我自己调用我自己:
- 每个对象都会有一个hashcode,Java可以通过这个hashcode来识别一个对象
-
this细节:
- this关键字可以访问,本类属性,方法,构造器
- 访问方法语法:this.方法名(参数列表)
- 访问构造器语法:this(参数列表) - 必须写在构造器中使用,必须在构造器中第一条中,不能递归调用(就是我调用你,你调用我)
- this关键字可以区分属性和局部变量
- this关键字只能在类定义的内部使用,去类外部使用谁知道this是什么
- this关键字可以访问,本类属性,方法,构造器
class AA{ String name; int age; public AA(String name, int age) { //this关键字访问本类构造器 this(\"小白\"); //this关键字访问本类属性 this.name = name; this.age = age; } public AA(String name) { String name = \"oop\"; //this关键字可以区分属性和局部变量 this.name = name; this.age = age; } public void t1(){ //this关键字可以访问本类方法 this.t2(); System.out.println(\"我是t1\"); } public void t2(){ System.out.println(\"我是t2\"); } }
来源:https://www.cnblogs.com/Mr-shne/p/16493472.html
本站部分图文来源于网络,如有侵权请联系删除。