# Java Day06 对象与变量

Java Day06

面向对象的语言

以事物的对象为核心 给事物发送消息指令来解决
对象适合做什么 我就封装成什么功能
代表语言 c# 、Java

特点

  1. 符合人们的思想
  2. 复杂事物简单化
  3. 从执行者变成指挥者

四大基本特性

  1. 封装
  2. 继承
  3. 多态
  4. 重载

构造方法 创建对象 初始化对象

构造方法 没有返回值
调用 在初始化时自动调用
构造方法 可以包含参数,参数一般是创建对象实例必须依赖的条件(前提条件)

注意:

类可以不声明构造方法,JVM会自动提供一个默认构造方法。如果自己提供一个构造方法,则不提供。

面向过程的语言 主要重在步骤 解决问题时

以事件的发展为驱动 c语言

把代码和数据根据不同的思维和理念分为两种。面向对象的语言和面向过程的语言


类和对象的区别

类 所有对象共有的特征 公共属性和行为的集合
对象 看得见的摸得着的

类的构造方法 需要注意:

构造方法的注意事项:
1、如果 class 中没有明确的定义出一个构造方法,那么虚拟机默认会给这个 class 提供一个没有参数的构造方法
2、构造方法的名称必须与类名相同
3、构造方法的定义处不能有任何返回类型的声明
4、不能在构造方法中使用 return 关键字
5、如果手动的在类里面写了构造方法,不管是有参数的,还是没有参数的,JVM将不再给这个类提供默认的构造方法
6、构造方法没有返回类型,甚至连void都没有
7、构造方法的调用是在创建一个对象时使用new操作符进行的;
8、构造方法可以包含参数,参数一般是创建对象实例必须依赖的条件(前提条件)。

重载:

构造方法重载的条件
与方法的重载一样,只要在同一个类中,方法名称完全相同,只是参数的个数,或类型不同或顺序不同就可实现构造方法的重载。
注:在实际开发中,如果类中有自定义构造方法,那么必须手动将无参构造方法写在类中。

对象

对象的实例化

  • 默认初始化
  • 显式初始化
  • 构造方法初始化

匿名对象

1、 定义:匿名对象就是没有名字的对象。是对象的一种简化表示形式。
2、匿名对象的两种使用情况(应用场景)
a. 对象调用方法仅仅一次的时候 ,一般如果这个对象只是用一次的时候采用
b. 作为实际参数传递

注:匿名对象只在堆内存中开辟空间,在栈内存中没有指向这个堆内存空间的地址
(例如:new Person();)

匿名对象的注意事项:
(1) 我们一般不会给匿名对象赋予属性值,因为永远无法获取到。
(2)两个匿名对象永远都不可能是同一个对象。

// 不具体命名 只用类来引用
new Person();

new Person("lisi",56);

对象构造次序

public class Day06_06 {
	int age = getAge();
	{ 
		System.out.println("aaaaaaaa");
    }
		public Day06_06() {
	    System.out.println("11111111");
   	    }
	     public int getAge(){
	     System.out.println("222222222");
		 return 21;
	     }
	public static void main(String[] args) {
		      new Day06_06();
    }
}

1.先去看一下这个类,有没有基类,如果有基类就先构造基类
2.在一个类中先初始化变量,变量中先初始化静态变量,然后是普通变量,然后再调用构造函数

面试题:

构造方法、成员变量初始化以及静态成员变量初始化三者的先后顺序是什么样的?

当类第一次被加载的时候,静态变量会首先初始化,接着编译器会把实例变量初始化为默认值,然后执行构造方法。

Java程序的初始化一般遵循以下三个原则(以下三原则优先级依次递减):

① 静态对象(变量)优先于非静态对象(变量)初始化,其中,静态对象(变量)只初始化一次,而非静态对象(变量)可能会初始化多次;

② 父类优先于子类进行初始化;

③ 按照成员变量定义顺序进行初始化,即使变量定义散布于方法定义中,它们依然在任何方法(包括构造方法)被调用之前先初始化。

Java程序初始化工作可以在许多不同的代码块中完成(例如静态代码块、构造方法等),它们执行的顺序如下:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造方法、子类非静态变量、子类非静态代码块和子类构造方法。

先后顺序是:静态成员变量、成员变量、构造方法。


变量

针对于类的变量分类

成员变量与类变量、局部变量、全局变量的区别:
类体由2部分构成: 一部分是变量的定义; 一部分是方法的定义(一个类中可以有多个方法)。
成员变量定义在类里的变量,定义的变量在整个类都有效。(作用域:整个类里)
类变量:在类里声明用static修饰的的变量是类变量
全局变量:是成员变量的俗称。作用域也是整个类里都有效。
局部变量:在方法中定义的变量,只在定义它的方法中有效。

判断依据: 根据变量定义的位置来确定。

成员变量和局部变量的区别:

1、在类中的位置不同
成员变量 类中方法外
局部变量 方法内或者方法声明上
2、在内存中的位置不同
成员变量 堆内存
局部变量 栈内存
3、生命周期不同
成员变量 随着对象的存在而存在,随着对象的消失而消失
局部变量 随着方法的调用而存在,随着方法的调用完毕而消失
4、初始化值不同
成员变量 有默认的初始化值
局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。

针对于内存分的变量分配

  • 引用变量:如声明的复合数据类型的变量是引用变量,指向对象存储内存的地址
  • 局部变量:只在局部可以被使用的变量。
    在方法内部定义的、方法的形参、游离块内部定义的变量属于局部变量。
  • 实例变量: 在类的声明中,属性是用变量来表示的。这种变量就称为实例变量

值传递和引用传递问题

1.值传递概念:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

实例:

public class Main {
    public static void main(String[] args) {
        int num  = 10;//实际参数
        test(num);
        System.out.println(num);//num的值没有被改变,任然为10;
    }
    //测试值传递的方法
    public static void test(int num){
        num = num + 10;
    }
}

2.引用传递:所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

实例:

public class Main {
    public static void main(String[] args) {
        Student student = new Student("zhangsan",20);//实际参数
        test(student);
        System.out.println(student);//结果为Student{name='lisi', age=20}
    }
    //测试引用传递的方法
    public static void test(Student student){
        student.setName("lisi");
    }
}

总结:值传递和引用传递都是传递的栈空间中的内容,因为栈空间存的是基本数据类型的值(所以表现为值传递),而栈空间存的引用类型的地址(所以表现为引用传递)。

如何区别值传递还是引用传递?

值传递 : 是一般是形参的改变 并且不会改变原来的值 因为它的值会被复制一份并改变
引用传递: 一般是对类对象改变 会改变类对象空间的数据 所以会改变原先存在的值

垃圾回收机制:

Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。

 内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。
 Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾回收算法一般要做2件基本的事情:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。

 Java的垃圾回收机制是Java虚拟机(JVM)提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。

需要注意的是:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身。

System.gc()
Runtime.getRuntime().gc()
上面的方法调用时用于显式通知JVM可以进行一次垃圾回收,但真正垃圾回收机制具体在什么时间点开始发生动作这同样是不可预料的,这和抢占式的线程在发生作用时的原理一样。

虽然垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new操作符创建的对象,如果某些对象不是通过new操作符在内存中获取一块内存区域,这种对象可能不能被垃圾回收机制所识别,所以在Java中提供了一个finalize()方法。这个方法是Object类的方法,它被声明为protected,用户可以在自己的类中定义这个方法。如果用户在类中定义了finalize()方法,在垃圾回收会首先调用该方法,在下一次垃圾回收动作发生时,才能真正回收被对象占用的内存。

修饰符:

ava中类的访问权限修饰符有private、default、protected、public,以下来分别介绍:

(1)私有权限(private)

private可以修饰数据成员、构造方法及方法成员,不可以修饰类。被他修饰的成员,只能在定义他们的类中使用,在其他类中不能使用;

(2)默认权限(default)

类、方法、成员都可以使用默认权限,即不被private、protected,public修饰。默认权限同包权限,同包权限下的元素只能在定义它们的类中以及同包的类中被调用;

(3)受保护权限(protected)

protected可以修饰数据成员、构造方法和方法成员,不可以修饰类。被protected修饰的成员能在它们的类中以及同包的类中被调用。如果有不同包的类想要调用它们,那这个类必须是他的子类;

(4)公共权限(public)

public可以修饰类、数据成员、构造方法及方法成员。被public修饰的成员,可以在任何一个类中被调用,不管同包或者不同包;

修饰符的类型

修饰符的类型
2.1 三种类的修饰符
public、abstract、final

2.2 三种构造函数的修饰符
public、protected、private

2.3 七种实例变量的修饰符
public、protected、private、static、final、transient、volatile

2.4 一种局部变量的修饰符
final

2.5 八种方法的修饰符
public、protected、private、static、final、abstract、native、synchronized

存储空间

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。

在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

java中变量在内存中的分配

1、类变量(static修饰的变量):在程序加载时系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期–一直持续到整个"系统"关闭

2、实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的"物理位置"。 实例变量的生命周期–当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存

3、局部变量:局部变量,由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放

附:java的内存机制

Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。

这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值