1.java内存划分
- Java的内存需要划分成为5个部分:
栈(Stack) :存放的都是方法中的局部变量。方法的运行一定要在栈当中运行。
局部变量:方法的参数,或者是方法{}内部的变量
作用域:一旦超出作用域,立刻从栈内存当中消失。 - 堆(Heap) :凡是new出来的东西,都在堆当中。
堆内存里面的东西都有一个地址值: 16进制
堆内存里面的数据,都有默认值。规则:
如果是整数 默认为0
如果是浮点数 默认为0.0
如果是字符 默认为’\u0000’
如果是布尔 默认为false
如果是引用类型 默认为null - 方法区(Method Area) :存储.class相关信息,包含方法的信息。
- 本地方法栈(Native Method Stack) :与操作系统相关。
- 寄存器(pc Register) :与CPU相关。
2.一个数组的内存情况
3.所有的引用类型变量,都可以赋值为一个null值,但是其中什么都没有
4.对象在内存中的表现
首先是方法区有.class文件(在这里,方法区中的方法会直接有一个地址,调用时将该方法地址进栈运行),然后main方法进栈,通过new,在堆内存中创建对象内存(主要里面的成员变量是模仿方法区的成员对象进行创建,然后里面的成员方法是只有一个方法区的的地址),当main方法中调用成员方法时,先找栈中对象的地址值进入堆,再在堆中寻找成员方法的地址,压栈,当成员方法运行完后,出栈,继续运行main方法。
5.成员变量和局部变量的区别
1)定义位置不一样
2)作用范围不一样
3)默认值不一样,成员变量没
有赋值时回有默认值,局部变量则没有默认值,没有赋值无法使用。
4)内存不一样,局部变量位于栈内存,成员变量位于堆内存
5)生命周期不一样,局部变量随着方法进出栈诞生消失,成员变量随着对象创建而诞生,随着对象被垃圾回收而消失。
6.匿名对象
- 正常标准格式 : 类名称 对象名 = new 类名称()
- 匿名对象是只有右边的对象,没有左边的名字和运算符
- 格式: new 类名称
- 注意事项:只能使用唯一的一次,下次再用得新建,且也不是原来那个
- 建议:确定一个对象只需要使用一次,就可以使用
- 作为参数和返回值
7.ArrayList类
- 数组长度不可以改变,但是 ArrayList 集合的长度可以任意改变
- 使用:尖括号<>中的E指泛型,指装在集合中的类型全都是统一的类型
- 对于arrylist集合来说,直接打印的不是地址值而是内容,内容为空则得到空的[ ]
- boolean add(E) 添加元素,对arrylist来说,一定成功,返回值可用可不用,但是对于其他集合来说不一定
- E get(int index)方法是获取对应位置的元素
- E remove(int index)删除对应位置的元素
- int size()获取集合的长度
8.String类
-
Java的API文档中指java程序中的所有字符串字面值(如"ABC")都作为此类的实例实现,也就是说程序中所有双引号字符串,都是String类的对象(没有new也是)。
-
特点
- 其中的内容无法改变,是常量
- 字符串可以共享使用
- 效果上相当于char[]字符数组,但是底层原理是byte[]字节数组。
-
/*字符串常量池:程序当中直接写上的引号字符串,就在字符串常量词中 对于基本类型来说,==是进行数值的比较![在这里插入图片描述](https://img-blog.csdnimg.cn/20200714213732427.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ExNzIzOTU1MDU=,size_16,color_FFFFFF,t_70) 对于引用类型来说,==是进行地址比较 */ String str1 = "abc"; String str2 = "abc"; char[] charArray = {'a', 'b', 'c'}; String str3 = new String(charArray); System.out.println(str1==str2);//true
双引号直接写的字符串在常量池中,new的不在池中
- 常用方法
/*
字符串比较方法
public boolean euqals(Object obj),参数可以是任何对象,只有参数是一个字符串并且
内容相同的才会给true,否则返回false
注意事项
1.任何对象都能用Object进行接收
2.equals方法具有对程序,即a.equals(b)和b.equals(a)效果一样
3.如果比较双方一个常量一个变量,推荐吧常量字符串写在前面
推荐:“abc".equals(str) 不推荐str.equals(“abc")
原因,如果str是null,就会出现空指针异常问题,如果是常量在前面,比较空值时会返回false
*/
String str1 = "abc";
String str2 = "abc";
char[] charArray = {'a', 'b', 'c'};
String str3 = new String(charArray);
System.out.println(str1.equals(str2));//true
System.out.println(str1.equals(str3));//true
System.out.println(str3.equals("abc"));//true
System.out.println("abc".equals(str1));//true
/*
另一个比较方法
public boolean euqalsIgnoreCase(String str),忽略大小写,进行内容比较
*/
/*
String当中与获取相关的常用方法:
public int length().获取字符串中的字符个数,即拿到字符串长度
public String concat(Sting str),将当前字符串与参数字符串拼接
public char charAt(int index),获取指定索引位置的单个字符串
public int indexof(String str),查找参数字符串在本字符串当中首次出现的索引位置,没有则返回-1
*/
public class StringDemo02 {
public static void main(String[] args) {
//获取字符串长度
int length = "sadsafasdasgfasfas".length();
System.out.println("字符串长度"+length);
//拼接字符串
String str1="hello";
String str2="world";
String str3=str1.concat(str2);
System.out.println(str1);//str1和2都不变
System.out.println(str2);
System.out.println(str3);//新字符串
System.out.println("========");
//获取指定位置的字符串
System.out.println("1号位置字符:"+"hello".charAt(1));
//查找参数字符串在原字符串出现的第一次索引位置,没有则返回-1
String original="helloworldhelloworld";
int index = original.indexOf("llo");
System.out.println("第一次索引值:"+index);
}
}
截取方法:subString
转换方法:toCharArray(),将当前字符串拆分成字符数组作为返回值
getBytes(),获得字符串底层的字节数据
public String replace(CharSequence oldString,CharSequence newString),将所有出现的老字符串替换成为新的字符串,返回替换之后的结果(新字符串)
public static void main(String[] args) {
//转换成为字符数组
char[] chars = "Hello".toCharArray();
System.out.print1n(chars[0]); // H
System.out.println(chars.1ength); // 5
System.out.print1n(===========");
//转换成为字节数组
byte[] bytes = "abc".getBytes();
for (int i =0; i < bytes .length; i++) {
System.out.print1n(bytes[i]);
}
System.out.print1("==========");
//字符串替换
String str1="How do you do?";
String str2=str1.replace("o", "*");
System.out.print1n(str1);
System.out.print1n(str2);
}
切割方法:split(String regex),按照参数,将字符串切分成若干部分
public static void main(String[] args) {
String str1 = "aaa,bbb,ccc";
String[] array1 = str1.split(",");
for (int i = 0; i < array1.1ength; i++) {
System. out .print1n(array1[i]);
}
System.out.println("===========");
//注意事项:split方法的参数其实时一个“正则表达式”
//如果按照英文句点“.”进行切分,必须写"\\."(两个反斜杠),因为“.”在正则表达式中有特殊含义
String str3 = "xxx.YYY.ZZZ";
String[] array3 = str3.split(".");
System. out.println(array3.length); // θ
for (int i = 0; i < array3.1ength; i++) {
System. out.print1n(array3[i]);
}
}
9.Static关键字
-
例子
-
如果一个成员变量前面用static标记,则这个变量属于类,所有成员变量共享同一份数据
-
一旦使用static修饰成员方法, 那么这就成为了静态方法。静态方法不属于对象,而是属于类的。如果没有static关键字,那么必须先创建对象,然后通过对象才能使用它
-
静态方法推荐用 类名.静态方法名来调用,用对象来调用的话容易造成误解;即无论是静态变量还是静态方法,如果有了static,都推荐使用类名称进行调用对于本类中的静态方法,可以省略类名称
-
注意事项:
- 成员方法可以访问静态变量,也可以访问非静态变量
- 静态方法可以访问静态变量,但不能直接访问非静态
- 原因:在内存中是先有的静态内容,后有的非静态内容
- 静态方法中不能使用this
- 原因:this表示当前对象,通过谁调用的方法,谁就是当前对象
-
内存图
-
静态代码块
/*
静态代码块的格式是:
public class类名称{
static {
//静态代码块的内容
}
}
特点:当第一次用到本类时,静态代码块执行唯一的一次。
静态总是优先于非静态,所有静态代码块比构造方法先执行
典型用途:
用来一次性地对静态成员变量进行赋值
*/
public class StaticDemo02 {
static {
System.out.println("静态代码块执行!");
}
public StaticDemo02(){
System.out.println("构造方法--");
}
public static void main(String[] args) {
StaticDemo02 one=new StaticDemo02();
StaticDemo02 two=new StaticDemo02();
}
}
10.Arrays的两个常用方法
import java.util.Arrays;
/*
java,util.Arrays是一个与数组相关的工具类,提供了大量静态方法,用来实现数组常见操作
public static String toString(数组):将参数数组变成字符串(按照默认格式:【元素1,元素2...】)
public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序,
备注:
1.如果是数值,sort默认按照升序从小到大
2.如果是字符串,sort默认按照字母升序
3.如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持。(今后学习)|
*/
public class ArraysMethodsDemo {
public static void main(String[] args) {
int[] intArray = {10,20,30};
String intStr = Arrays.toString(intArray);
System.out.println(intStr);
int[] arry1={2,3,1,6,4};
Arrays.sort(arry1);
System.out.println(Arrays.toString(arry1));
}
}
11.Math数学工具类
/*
java. util .Math类是数学相关的工具类, 里面提供了大量的静态方法,完成与数学运算相关的操作。
public static double abs(double num): 获取绝对值。
public static double ceil(double num): 向上取整。
public static double floor(double num): 向下取整。
Math.PI,静态变量,待变近似的圆周率变量
*/
public class MathDemo {
public static void main(String[] args) {
//狱取把对值
System.out.println(Math.abs(3.14)); // 3.14
System.out.println(Math.abs(0)); //0
System.out.println(Math.abs(-2.5)); // 2.5
System.out.println("=============");
//向上取整
System.out.println(Math.ceil(3.9)); // 4.0
System.out.println(Math.ceil(3.1)); // 4.0
System.out.println(Math.ceil(3.0)); // 3.0
System.out.println("=============");
//向下取整,抹零
System.out.println(Math.floor(30.1)); // 30.0
System.out.println(Math.floor(30.9)); // 30.0
System.out.println(Math.floor(31.0)); // 31.0
System. out . println("=============");
System. out . println(Math. round(20.4)); // 20
System. out . println(Math. round(10.5)); // 11
}
}
12.继承
- 继承是多态的前提,如果没有继承,就没有多态
- 继承主要解决的问题是:共性抽取
- 特点
- 子类可以拥有父类的“内容”
- 子类可以拥有自己独有的“内容”
示例图:
/*
在继承的关系中,子类就是一个父类”。 也就是说,子类可以被当做父类看待。
例如父类是员工,子类是讲师,那么“讲师就是一个员工”。 关系: is-a.
定义父类的格式,(一个普通的类定义)
public class 父类名称{
}
定义子类的格式,
public class子类名称extends 父类名称{
// ..
}
*/
public class ExtendsDemo01 {
public static void main(String[] args) {
Employee employee=new Employee();
//创建子类对象
Teacher teacher=new Teacher();
//里面什么都没有,但是会继承Employe的方法
teacher.method();
Assistant assistant=new Assistant();
assistant.method();
/*
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
直接通过子类 对象访问成员变量:
等号左边是谁,就优先使用谁,没有则向上找
间接通过成员方法访问成员变量:
该方法属于谁(定义在子类还是弗雷),就优先使用谁,没有则往上找
*/
System.out.println("fu "+employee.fu);
System.out.println("zi1 "+teacher.zi);
System.out.println("zi2 "+assistant.zi);
teacher.methodzi();
}
}
方法覆盖重写的注意事项:
1.必须保证父子类之间方法的名称相同,参数列表也相同。
@Overrider.写在方法前面,用来检测是不是有效的正确覆盖重写。
这个注解就算不写,只要满足要求,也是正确的方法覆盖
2.子类方法的返回值必须小于等于父类方法的返回值范围。
小拓展提示: java.lang.object类是所有类的公共最高父类 (祖宗类),java.lang.String就是object的子类。
3.子类方法的权限必须[大于等于]父类方法的权限修饰符。
小扩展提示: public>protected>(default)>private
备注: (default)不是关键字defoult,而是什么都不写,留空。
(返回值类型也是,返回值必须是父类返回值的子类才可以,比如父类Object,子类String)
-
继承的使用场景
设计原则:对于已经投入使用的类,尽量不要进行修改。推荐定义一个新的类,来重复利用其中共性内溶,井且添加改动新内容。 -
访问特点
继承关系中,父子类构造方法的访问特点:
1.子类构造方法当中有一个默认隐含的"“super()”周用,所以一定是先调用的父类构造,后执行的子类构造。
2.子类构造可以通过super关键字来调用父类重载构造。
3.super的父类构造调用, 必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
总结:
子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个, 还必须是第一个。 -
super关键字的三种用法:(用来访问父类内容)
1.在子类的成员方法中,访问父类的成员变量。
2.在子类的成员方法中,访问父类的成员方法。
3.在子类的构造方法中,访问父类的构造方法。 -
this关键字的三种用法:(用来访问本类内容)
1.在本类的成员方法中,访问本类的成员变量。
2.在本类的成员方法中,访问本类的另-一个成员方法。
3.在本类的构造方法中,访问本类的另一个构造方法。
在第三种用法当中要注意,this(… )调用也必须是构造方法的第一个语句。super和this两种构造调用,不能同时使用
public class Fu {
int num = 30;
}
public class Zi extends Fu {
int num=20;
public Zi() {
super();
this( n 123); //本类的无参构造,调用本类的有参构造
//this(1, 2); //错误写法!
}
public Zi(int n) {
}
public zi(int n, int m) {
}
public void shouNum() {
int num=10;
System.out.println(num); //. 局部变量
System.out.println(this .num); //本类中的成员变量
System.out.print1n(super.num); //父类中的成员变量
}
public void methodA() {
System.out.print1n("AA");
}
public void methodB() {
this.methodA();
System.out.print1n("BBB");
}
}
-
super和this的关键字图解
-
Java继承的三个特征
Java语言是单继承的。一个类的直接父类只能有唯一个。
例子:
class A {}
class B extends A {} //正确
class C {}
class D extendsA, C {} //错误
示例图
Java语言可以多级继承。
“我有一个父亲,我父亲还有一个父亲,也就是爷爷。”
classA{}
class B extends A {} //正确
class C extends B {} //正确
一个子类的直接父类是唯一的, 但是一个父类可以拥有很多个子类。
class A {}
class B extends A {} //正确
class C extends A {} //正确