JAVA基础入门笔记(三)

目录

一:面向对象和面向过程的区别与联系

二:类的定义

三.方法

四.数组

四.程序执行的内存分析

五:equals与==的用法


一:面向对象和面向过程的区别与联系

面向过程:顾名思义就是一步一步来,比如你要开一辆车,整个流程就是:点火,发动-->挂挡-->踩油门-->走你。面向过程适合简单,不需要协作的事务,重点关注如何执行。

但是当我们思考比较复杂的设计任务时,比如“如何造车”,就会发现很难列出一个具体的步骤,因为涉及的东西太多,造车复杂,需要很多协作,分类才能完成。此时面向对象的思想就派上用场了。

面向对象:针对“如何造车”这个问题进行解释,面向对象可以理解成是从“车怎么设计”这个角度去思考,而不是思考“怎么按步骤去造车”。因此,我们会把汽车分为许多部位,如轮胎,发动机,玻璃,座椅,车壳等等。为了便于协作,我们找轮胎厂完成制造轮胎的任务,发动机厂完成制造发动机的任务......各个厂家各司其职,彼此分工协作,最终进行组装,大大提高了效率。但是,具体到制造每一个精确的器件的时候,仍然具有步骤的,此时仍然离不开面向过程的思维。

因此,面向对象是从宏观上来把握,从整体上分析整个系统。但是,具体到实现部分的微观操作,仍然需要面向过程的思路去处理。

  • 面向过程和面向对象思想的总结
  1. 都是解决问题的思维模式,都是组织代码的方式。
  2. 面向过程是一种“执行者思维”,解决简单问题可以使用面向过程。
  3. 面向对象是一种“设计者思维”,解决复杂,需要协作的问题可以使用面向对象。
  4. 面向对象离不开面向过程:
  • 宏观上:通过面向对象进行整体的设计。
  • 微观上:执行和处理数据,仍然是面向过程。

二:类的定义

(1)类由三部分组成:属性,方法,构造方法(构造器)。

每一个源文件必须有且只有一个public class,并且类名和文件名相同。

public class SxtStu{
//属性(成员变量)
int id;
String name;
int age;
//方法
  void study(){
    System.out.println("你好!);
  }
//构造方法(方法名和类名保持一致)
    SxtStu(){
    }

}

(2) 构造器也叫构造方法,用于对象的初始化。构造器是一个创建对象时被自动调用的特殊方法,目的是对象的初始化。构造器的名称应与类的名称一致。Java通过new关键字来调用构造器,从而返回该类的实例(对象),是一种特殊的方法。

声明格式:

[修饰符]  类名 (形参列表){

//具体代码

}

(3)构造器的要点

  1. 构造器通过new关键字调用
  2. 构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return返回某个值。
  3. 如果没有定义构造器,则编译器会自动定义一个无参的构造函数。如果已经定义,则编译器不会自动添加。
  4. 构造器的方法必须和类名一致。
  5. 构造方法(构造器)也是方法,只不过有特殊的作用而已。于普通方法一样,构造方法也可以重载。
  6. 在用构造方法创建一个新的对象时,还可以同时实现某些功能,如输出,赋值等等

三.方法

(1)声明格式:

[修饰符1   修饰符2...] 返回值类型 方法名 (形参){

java语句;.......

}

public static int add(int a, int b, int c){
        int sum = a+b+c;
     return sum;
}

(2)方法的调用:

对象名.方法名(实参)

四.数组

(1)动态初始化(声明并开辟数组):数组的大小或数组中的数据在程序运行时才能决定,且用到new这个关键字来确定数组的大小或初始数据我们称之为动态初始化。

a.声明与开辟数组同步:数据类型 [ ] 数组名 = new 数据类型 [数组长度];

b.声明与开辟数组分步

数据类型 [ ]   数组名;   //声明数组

数组名 = new 数据类型 [length];   //初始化一个长度为length的数组

(2)静态初始化:在程序运行之前就能确定数组的大小或数组中的数据。


//简化格式
数据类型[] 数组名称 = {值,值,....} (只有基本类型数据可以这样)
//完整格式
数据类型[] 数组名称 = new 数据类型[] {值,值,....}//等式右边的[]里面为空(非基本类型数据的数组初始化只能用于声明同事赋值的情况下)

例如:

float [] stu={80.0f,70.0f,90.0f,66.5f};

int [] nums={80,70,60,50};

char [] chs={'a','b','c'};

String [] names=new String [] {"张三","李四","王五"};//等式右边的[]里面必须为空

new不new没多大关系,只要让数组变量指向一个有效的数组对象,程序即可正常使用该数组变量。

(3)

对于数组变量来说,它并不需要进行所谓的初始化,只要让数组变量指向一个有效的数组对象,程序即可正常使用该数组变量。所以,Java语言中的数组,不一定要初始化也可正常使用。

public class T {  
 
  public static void main(String[] args) {  
 
    //定义并初始化nums数组  
 
    int nums[] = new int[]{3,13,4,6};  
 
    //定义一个prices数组变量  
 
    int prices[];  
 
    //让prices数组指向nums所引用的数组  
 
    prices = nums;  
 
    for(int i=0;i<prices.length;i++){  
 
      System.out.println(prices[i]);  
 
    }  
 
    //将prices数组的第三个元素赋值为100  
 
    prices[2] = 100;  
 
    //访问nums数组的第三个元素 将看到数组100  
 
    System.out.println(nums[2]);  
 
  }  
 
} 

当程序执行prices = nums之后,prices变量将指向nums变量所引用的数组,此时prices变量和nums变量引用同一个数组对象。执行这条语句之后,prices变量已经指向有效的内存及一个长度为4的数组对象,因此程序完全可以正常使用prices变量了。

四.程序执行的内存分析

1、在内存中分为所谓的栈、堆、方法区
栈:自动分配的连续的空间,后进先出,通常用于存放局部变量
堆:不连续的空间,用于存放new出来的对象
方法区:方法区也是堆,用于存放类的信息(如代码),static变量、常量池

ps:不论是基本数据类型还是引用类型,他们都会先在栈中分配一块内存,对于基本类型来说,这块区域包含的是基本类型的内容;而对于引用类型来说,这块区域包含的是指向真正内容的指针,真正的内容被手动的分配在堆上。

通过下面代码进行内存分析

public class Person {
    String name;
    int age;
    public void show(){
        System.out.println("姓名:"+name+",年龄:"+age);
    }
}
public class TestPerson {
    public static void main(String[ ] args) { // 创建p1对象
        Person p1 = new Person();
        p1.age = 24;
        p1.name = "张三";
        p1.show();
        // 创建p2对象
        Person p2 = new Person();
        p2.age = 35;
        p2.name = "李四";
        p2.show();
    }
}

public static void main(String[] args)

从main方法开始执行,首先在虚拟机栈中建立一个main方法的栈帧,main方法也有形参,形参为String[] args。args为null;

Person p1 = new Person();

然后创建了一个新的对象p1,p1的初始值为null,于是需要在堆中为p1开辟一块新的地址空间,假设地址为0x11,p1的值即为0x11, name初始值为null,age初始值为0,show方法是一个公有的东西,所以应该将show方法的信息放在存放在方法区里的Person类里面,同时new Person( )调用了Person类的构造方法,故应在虚拟机栈中为构造方法也创建一个栈帧。Person p1 = new Person();运行结束后,构造方法的帧栈出栈。至此,Person p1 = new Person();的内存分析就算完成了。

p1.age = 24;
p1.name = "张三";
p1.show();

继续往下执行,age的值为24,由于字符串不是基本数据类型,所以"张三"这个字符串应该放在Person类的常量池里,show方法的信息也存放在Person类里。p1.show( ),show方法被调用,所以应在虚拟机栈中创建一个帧栈(构造方法的帧栈已经出栈),this指当前对象p1,故地址为0x11.。p1.show( )运行结束后,其帧栈出栈。

  p2的内存分析与p1一样。直到程序运行结束,所有东西都被清空。

另外栈有一个很重要的特殊性,就是存在栈中的数据可以共享。如 需要定义int a = 3; int b =3;这两个自动变量。编译器先处理int a=3;首先在栈中创建一个变量为a的引用,然后查找栈有没有字面值为3的引用,没有找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b=3;在创建完b这个引用变量后,由于在栈中已经有了3这个字面值,即将b直接指向3的地址。这样,就出现了a和b同事指向3的情况。 定义完a与b后,在令a=4,那么b不会等于4,而是等于3,。在编译器内部,遇到时,它就会中新搜索栈中是否有4这个字面值,如果没有,重新开辟地址存放4的值。如果已经有就直接将a指向这个地址,因此a的值改变不会影响b的值。

五:equals与==的用法

栈区存引用和基本类型,不能存对象,而堆区存对象。==是比较地址,equals()比较对象内容。

== 是比较内存地址是否相同,而equals 是针对引用数据类型的方法,取出内存地址中的值比较是否相同。

(1)要判断两个基本数据类型的变量是否相等,只能用==不可以用equals。基本数据类型无equals方法,因为所有的基本数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,Java语言里面八种数据类型(byte,short,int,long,float,double,char,boolean)是这种存储模型;

(2)String类

String s1 = "latiny";

String s2 = "latiny";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
String s3 = new String("latiny");

String s4 = new String("latiny"); 
System.out.println(s3 == s4);
System.out.println(s3.equals(s4));
输出结果:
true
true
false
true

String str1 = "abcd"的实现过程:首先栈区创建str引用,然后在String池(独立于栈和堆而存在,存储不可变量)中寻找其指向的内容为"abcd"的对象,如果String池中没有,则创建一个,然后str指向String池中的对象,如果有,则直接将str1指向"abcd"";如果后来又定义了字符串变量 str2 = "abcd",则直接将str2引用指向String池中已经存在的“abcd”,不再重新创建对象;当str1进行了赋值(str1=“abc”),则str1将不再指向"abcd",而是重新指String池中的"abc",此时如果定义String str3 = "abc",进行str1 == str3操作,返回值为true,因为他们的值一样,地址一样,但是如果内容为"abc"的str1进行了字符串的+连接str1 = str1+"d";此时str1指向的是在堆中新建的内容为"abcd"的对象,即此时进行str1==str2,返回值false,因为地址不一样。

 String str3 = new String("abcd")的实现过程:直接在堆中创建对象。如果后来又有String str4 = new String("abcd"),str4不会指向之前的对象,而是重新创建一个对象并指向它,所以如果此时进行str3==str4返回值是false,因为两个对象的地址不一样,如果是str3.equals(str4),返回true,因为内容相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笃岩_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值