java面向对象
面向对象的开发,设计,特征
-
面向对象的开发:就是不断的创建对象,使用对象,指挥对象做事情
面向对象的设计:就是设计与管理对象之间的关系
面向对象的特征:封装、继承、多态 -
封装
在开发项目的时候,需要不断的去声明类,在类中需要去封装属性和行为,但是针对于某一些属性,我们需要将它保护起来,不希望外界可以直接的访问,所以将这些属性用private关键字修饰,private代表的是私有的访问权限修饰符。这些属性只能在本类中直接访问,不能在其他类之外进行直接访问。
-
getter、setter
类的属性值为private的时候,在外部类要调用或者修改这些属性值,则需要通过调用对应的get和set函数来修改属性值。
内存分配
-
栈内存、堆内存、方法区内存
- 定义在类中的实例变量一定是在堆内存中开辟的空间,因为new出来的部分一定存在于堆内存中。
- 在JVM内存中,所有的方法,无论是静态方法还是普通方法(实例方法),都是在栈中分配内存空间。
- 方法区内存中一般存放的是代码片段(java源文件编译之后的字节码文件),即各种用到的类的.class字节码文件。同时还有一个常量池,用于存放字符串数据。
- 局部变量和实例变量的区别:局部变量是存在于方法体内部的变量(包含参数),局部变量如果是基本数据类型,则直接在栈中开辟空间,如果是引用数据类型,变量声明部分在栈中,实例创建部分在堆中,如果是实例变量,所有的内存都会在堆中开辟。
int[] ints=new int[10]; ints[0]=1; ints[1]=2; User user1=new User();
- 数组类型是引用数据类型,会先在栈内存中开辟一个变量声明的内存空间,存放变量名及映射到堆内存的地址,然后在堆内存中进行实例创建空间的分配。后续的赋值则在分配的堆内存空间内进行划分。User用户类也是引用数据类型,先在栈内存中开辟user1的内存,并赋值为地址。然后在堆内存中会为user1开辟一个内存空间,用于存放user1的属性,比如userName,userAddress等。
- Student student=new Student();在内存中做了哪些事情
加载Student.class文件进内存;
在栈内存为student开辟空间;
在堆内存为学生对象开辟空间;
根据构造方法初始化;
通过构造方法对学生对象的成员变量赋值;
学生对象初始化完毕,把对象地址赋值给student变量;
-
案例
- 通过String类来说明不同变量在内存中的分配问题
/**
* 通过==,如果比较的是基本数据类型,则比较的是值,如果比较的是引用数据类型,则比较的是内存地址值
*/
public class StringTest01 {
public static void main(String[] args) {
//"hello world"存在方法区中的常量池中 所以str声明在栈内存中,值为“hello world”在方法区中的地址值
String str="hello world";
//str1声明部分在栈内存中 存放的是堆内存中的内存地址,同时堆内存又因参数 所以还会指向方法区内存中的常量池中"hello world"地址
String str1=new String("hello world");
String str2="hello world";
String str3=new String("hello world");
System.out.println(str==str1);//false
System.out.println(str==str2);//true 因为"hello world“都是位于常量池的同一个地址
System.out.println(str1==str3);//false
}
}
static关键字
-
静态关键字 static:
可以修饰方法,属性,不能修饰类,被静态关键字static修饰的属性和方法,会成为类级别的元素,会随着类的加载而加载,JVM在加载字节码文件的时候,也会加载被static修饰的元素。
静态变量内存是在方法区中的,而静态方法内存是在栈内存中。因为所有方法的内存都是分配在栈内存中。
写在方法体内的变量是局部变量,没法加static形成类级别,static只能修饰实例变量成为静态变量,静态变量会随着类的加载而加载,在JVM解析字节码文件的时候,该变量的内存空间就会被开辟出来,静态变量的内存空间会被开辟在方法区内中。
成员变量:实例变量、静态变量
局部变量:方法体内的变量(包括参数中的变量) -
静态代码块:
在类加载的时候将会被执行的语句体,而且只加载一次,如果第二次解析这个类,将不会被加载,并且会在主函数执行之前执行。
public static void main(String[] args) {
System.out.println("main 执行了!");
}
static {
System.out.println("static 执行了!");
}
输出结果:
static 执行了!
main 执行了!
静态变量与成员变量的区别
-
所属不同
静态变量属于类,也称为类变量;
成员变量属于对象,也称为实例变量;
-
内存中位置不同
静态变量存储在方法区中的静态区
成员变量存储在堆内存中
-
内存出现时间不同
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
-
调用不同
静态变量可以通过类名调用,也可以通过对象调用成员变量只能通过对象名调用
toString()方法
当一个类并没有继承任何特定的一个父类的时候,该类会继承一个object类(所有类的父类)可以点击object查看源码中的toString方法:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
所以当我们每次System.out.println(类名)的时候,会输出当前类名+@+哈希值。eg:
User@4554617c
如果我们重写了toString方法,那么当我们再次System.out.println(类名)的时候,
就会出现toString重写方法里面输出形式.
User{userName='张三', idCard='123'}