前言:
- 引出类与对象(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);
- }
- <br>//有参返回
- 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是什么
- 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");
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |