java内存划分
Java的内存划分为5个部分:
1.栈 (Stack) : 存放的都是方法中的局部变量,方法的运行一定要在栈当中
局部变量: 方法的参数,或者是方法()内部的变量
作用域: 一旦超出作用域,立刻从栈内存当中消失
2.堆(Heap): 凡是new出来的东西,都是在堆当中
堆内存里面的东西都有一个地址值:16进制
堆内存里面的数据,都有默认值,规则:
整数 默认值0
浮点数 默认值0.0
字符 默认值'\u0000'
布尔 默认值false
引用类型 默认值null
3.方法区(Method Area):存储class相关的信息,包含方法的信息
4.本地方法栈(Native Method Stack): 于操作系统相关
5.寄存器 (pc Register): 与CPU相关
局部变量和成员变量
局部变量和成员变量:
1.定义的位置不一样
a.局部变量:在方法的内部
b.成员变量:在方法的外部,直接写在类当中
2.作用范围不一样
a.局部变量:只有方法当中才可以使用,出了方法就不能再用
b.成员变量:整个类全都可以通用
3.默认值不一样
a.局部变量:没有默认值,如果想想用,必须手动进行赋值
b.成员变量:如果没有赋值,会有默认值,规则和数组一样
4.内存的位置不一样
a.局部变量:位于栈内存
b.成员变量:为于堆内存
5.生命周期不一样
a.局部变量:随着方法进栈而诞生,随着方法出栈而消失
b.成员变量:随着对象 创建而诞生,随着对象被垃圾回收机制回收而消失
构造方法
构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法
public 类名(参数类型 参数){
}
主要事项:
1.构造方法的名称必须和所在的类名称完全一样,就连大小写也要一致
2.构造方法没有返回值,void也不写
3.构造方法不能return一个具体的返回值
4.如果没有编写任何构造方法,那么编辑器会默认增加一个构造方法
5.构成方法也是可以重载的
标准类
一个标准的类通常要拥有下面四个组成部分:
1.所有的成员变量都要用private关键字修饰
2.为每一个成员变量编写一对Getter和Setter
3.编写一个无参的构造方法
4.编写一个有参的构造方法
private
private 定义的成员属性,只能在本类中访问,超出本类就不能访问了
间接访问private成员变量,就是定义一对Getter/Setter
必须叫setxxx或者getxxx命名规则
对于Getter来说,不能有参数,必须有返回值,返回值类型必须和成员变量类型一致
对于Setter来说,不能有返回值,必须有参数,参数类型必须和成员变量类型一致
数组概念
数组概念:是一个容器,可以同时存放多个数据值
数组的特点:
1.数组是一种引用数据类型
2.数组当中的多个数据类型必须一致
3.数组的长度在程序运行期间不可改变
两种常见的初始化方式:
1.动态初始化(指定长度)
2.静态初始化(指定内容)
动态初始化数组的格式:
数据类型[] 数组名称 = new 数据类型[数组长度]
静态初始化数组的格式:
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,...}
注意事项:
1.静态初始化没有直接指定长度,但是任然可以自动推算的到长度
2.静态初始化标准格式可以拆分成为两个步骤
3.动态初始化也可以拆分为两个步骤
4.静态初始化一旦时候省略号,就不能拆分为两个步骤
使用建议:
如果不确定数组当中的具体内容,用动态初始化,否则,已经确定了具体的内荣,用静态初始化
ArrayList集合
数组的长度是不可以改变的
但是ArrayList集合的长度是可以随意改变的
对于ArrayList来说,有一个尖括号<E>代表泛型
泛型:也就是装在集合当中的所有元素,全都是统一什么类型
注意:泛型只能是应用数据类型,不能是基本数据类型
注意事项:
对于ArrayList集合来说,直接打印得到的不是地址,而是内容
如果内容是空,得到的是空的括号[]
ArrayList当中的常用方法有:
public boolean add(E e); 向集合当中添加元素,参数的类型和泛型一致;返回值代表添加是否成功
备注:对于ArrayList集合来说,add添加动作一定是成功的,所以返回值可以不用
但对于其他集合来说,add添加动作不一定成功
public E get(int index); 从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素
public E remove(int index); 从集合当中删除元素,参数索引编号,返回值就是被删除出掉的元素
public int size();获取集合的尺寸长度,返回值是集合中包含的元素个数
如果希望向集合ArrayList集合当中存储基本数据类型,必须使用基本类型对的"包装类"
基本类型 包装类 (应用类型 包装类都位于Java.lang包下)
byte Byte
int Integer
short Short
long Long
float Float
double Double
char Character
boolean Boolean
从JDK1.5开始,支持自动装箱、自动拆箱
自动装箱:基本类型 --> 包装类型
自动拆箱:包装类型 --> 基本类型
public class DemoArrayList {
public static void main(String[] args) {
//创建了一个ArrayList集合,集合的名称是arrList,里面装的全都是String类型的字符串数据
//备注:从JDK1.7开始,右侧的尖括号内部可以不写内容,但是<>本事还是要写的
ArrayList<String> arrList = new ArrayList<>();
System.out.println(arrList);
//向集合中添加数据
arrList.add("123");
arrList.add("马三");
boolean success = arrList.add("王五");
System.out.println(arrList);
System.out.println(success);
//从集合中获取元素,get
String str = arrList.get(1);
System.out.println(str);
//从集合中删除元素 remove
String whoRome = arrList.remove(2);
System.out.println("被删除的人:"+whoRome);
System.out.println(arrList);
//size(),获取集合的长度
int len = arrList.size();
System.out.println(len);
//遍历集合
for (int i = 0; i < arrList.size(); i++) {
System.out.println(arrList.get(i));
//定义一个可用存储int类型的数组
ArrayList<Integer> listC = new ArrayList<>();
listC.add(1);
listC.add(2);
listC.add(3);
System.out.println(listC);
int num = listC.get(1);
System.out.println(num);
}
}
}
static关键字
如果一个成员变量使用了static关键字,那么这个变量不在属于对象自己,而是属于所在的类,多个对象共享一份数据
如果一个成员方法使用了static关键字,那么这个方法不在属于对象自己,而是属于所在的类,多个对象共享一个发方法
如果有了static关键字,那么不需要创建对象,直接就用类名来使用它
无论是成员变量,还是成员方法,如果有了static关键字,都推荐使用类名称进行调用
静态变量:类名称.静态变量
静态方法:类名称.静态方法()
注意事项:
1.静态不能直接访问非静态
原因:因为在内存当中是先有静态内容,后有非静态内容
2.静态方法当中不能用this关键字
原因:this代表当前对象
3.根据类名称访问静态变量的时候,全程和对象没有关系,只和类有关系
静态代码块的格式:
public class 类名称{
static {
代码块类容
}
}
特点:当第一次用到本类时,静态代码块执行唯一的一次
静态内容总是优先于非静态内容,所以静态代码块比构造方法先执行
静态代码块的典型用途:
用来一次性地对静态成员变量进行赋值
继承
局部变量:直接写变量名
本类的成员变量:this.成员变量名
父类的成员变量:super.成员变量名
重写:(Override) 方法的名称一样,参数列表也一样
注意事项:
1.必须保证父子类之间方法的名称相同,参数列表也相同
@Override(注解):写在方法前面,用来检测是不是有效的正确覆盖重写
2.子类方法的返回值必须小于等于父类方法的返回值范围
3.子类方法的权限必须大于等于父类方法的权限修饰符
public > protected > (default) > private
使用场景:
共性抽取
继承关系中,父子类构造方法的访问特点:
1.子类构造方法当中有一个默认隐含的"super()"调用,所以一定是先调用的父类构造方法,后执行的子类构造方法
2.子类构造可以通过super关键字来调用父类重载构造方法
3.super的父类构造调用,必须是子类构造方法的第一句,不能一个子类构造多次调用super构造
总结:
子类必须调用父类构造方法,不写则赠送一个super();写了则用写的指定的super()调用,super只能有一个,还必须是第一个
super关键字的三种用法:是用来访问父类内容的
1.在子类的成员方法中,访问父类的成员变量
2.在子类的成员方法中,访问父类的成员方法
3.在子类的构造方法中,访问父类的构造方法
this关键字是的用法:是用来访问本类的内容
1.在本类的成员方法中,访问本类的成员变量
2.在本类的成员方法中,访问本类的另一个成员方法
3.在本类的构造方法中,访问本类的另一个构造方法;例如:无参构造调用有参构造
注意:
1.this(...)调用也必须是构造方法的第一个语句,唯一一个
2.super和this两种构造调用,不能同时使用
重载:(Over) 方法名称一样,参数个数或者参数类型不一样
String字符串以及比较
java.lang.String类代表字符串
程序中所有的双引号字符串,都是String类的对象(就算没有new 也是一样的)
字符串的特点:
1.字符串的内容永远不可变
2.正是因为字符串不可改变,所以字符串是可以共享使用的
3.字符串效果相当于char[]字符数组,但是自层原理byte[]字节数组
创建字符串的常见方式
1.public String();创建一个空白字符串,不含任何内容
2.public String(char[] array);根据字符数组的内容,创建对应的字符串
3.public String(byte[] array);根据字节数组的内容,创建对应的字符串
字符串常量池:程序中直接写上的双引号字符串,就在字符串常量池中
对于基本类型来说:==是进行数值的比较
对于应用类型来说:==是进行地址值的比较
==是进行对象的地址值的比较,如果确实需要进行字符串的内容比较,可以使用以下两种方法:
public boolean equals(Object obj) 参数可以是任何对象,只有参数是一个字符串并且内容相同的才会给true,否则返回false
注意事项:
1.任何对象都可以用Object进行比较
2.equals方法具有对称性,也就是a.equals(b)和b.equals(a)效果一样
3.如果比较双方一个是常量一个是变量,推荐把常量字符串写在前面
推荐:"abc".equals(str) 不推荐:str.equals("abc")
public boolean equalsIgnoreCase(String str) 忽略大小写,进行内容比较
public class DemoString02 {
public static void main(String[] args) {
String str1 = "hello";
String str2 = "hello";
char[] charArray = {'h','e','l','l','o'};
String str3 = new String(charArray);
System.out.println(str1.equals(str2));
System.out.println(str2.equals(str3));
//当str3为null时,str3.equals("hello")会报错,NullPointerException
System.out.println("Hello".equals(str3));
System.out.println("Hello".equalsIgnoreCase(str3));
// System.out.println(str3.equals("hello"));
}
}
字符串的获取常用方法
String 当中与获取相关的常用方法有:
public int length(): 获取字符串当中含有的字符个数,拿到字符串长度
public String concat(String str): 将当前字符串和参数字符串拼接成为返回新的字符串
public char charAt(int index): 获取指定索引位置的单个字符。索引从0开始
public int indexOf(String str): 查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1
public class DemoString03 {
public static void main(String[] args) {
//获取字符串长度
int length = "fdlsafjdsafdsjafld".length();
System.out.println("字符串长度:"+length);
System.out.println("======================");
//拼接字符串
String str1 = "Hello";
String str2 = "World";
String str3 = str1.concat(str2);
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
System.out.println("======================");
//获取指定索引位置的单个字符
char ch = "Hello".charAt(1);
System.out.println("索引位置为1的字符为:"+ch);
System.out.println("======================");
//查找字符串在本字符串中首次出现的位置
String str4 = "helloWorld";
int index = str4.indexOf("ll");
System.out.println("第一次出现索引的位置:"+index);
//字符串不存在时,返回-1
System.out.println("helloWorld".indexOf("add"));
}
}
字符串的截取常用方法
public String substring(int index): 截取从参数位置一直到字符串结尾,返回新字符串
public String substring(int begin, int end): 截取从begin开始,一直到end结束,中间的字符串
备注:[begin,end)
public class DemoString04 {
public static void main(String[] args) {
String str = "HelloWorld";
String str1 = str.substring(5);
System.out.println(str);
System.out.println(str1);
String str3 = str.substring(4,7);
System.out.println(str3);
/*
下面这种写法,字符串的内容任然是不变的
下面两个字符串:"Hello"和"Java"
str4当中保存的是地址值
本来的地址值是Hello的0x666
后来地址值变成了Java的0x999
*/
String str4 = "Hello";
str4 = "Java";
System.out.println(str4);
}
}
字符串转换常用方法
public char[] toCharArray();将当前字符串拆分成为字符数组作为返回值
public byte() getBytes();获取当前字符串底层的字节数组
public String replace(CharSequence oldSting, CharSequence newString)
将所有出现的老字符串替换为新的字符串,返回替换之后的结果新字符串
public class DemoStringConvert {
public static void main(String[] args) {
char[] chars = "Hello".toCharArray();
System.out.println(chars[0]);
System.out.println(chars);
System.out.println(chars.length);
//转换成为字节数组
byte[] bytes = "abc".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
//字符串替换
String str1 = "How do you do?";
String str2 = str1.replace("o", "@");
System.out.println(str1);
System.out.println(str2);
}