文章目录
JDK、JRE、JVM之间的关系
- JDK——java程序开发工具包,包含JRE和开发工具,其中开发工具包括编译工具(javac.exe)和运行工具(java.exe)
- JRE——java runtime environment,java程序运行环境
- JVM——java虚拟机
常用DOS命令
DOS磁盘操作系统,需要掌握常见的DOS命令
- 编译:javac HelloWorld.java
- 运行:java HelloWorld
数据类型
- 由于int是整数默认值,当我们定义如
long a = 10000000000;
时,左边默认int类型超出内存了,long a = 10000000000L;
就可以解决。 - 同理,
float b = 0.1F;
类型转换
- 自动类型转换 :
占用内存小的可以自动转换成内存大的类型。
- 强制类型转换:
目标数据类型 变量名 = (目标数据类型)值或者变量名
字符的+操作和字符串的+操作
- 字符+:
'A’→65,‘a’→97,‘0’→48。
表达式中包含多种基本数据类型时,表达式最终类型以内存最大的为准。 - 字符串+:
从左向右,叠加直到出现字符串然后字符串拼接起来。
1 + 99 + "java" // output: 100java
"java" + 1 + 99 // output: java199
赋值操作(=)
值得注意的是,类似于+=操作隐含了强转数据类型。定义a是short类型。
a = a + 20; // 报错,右边是int类型,解决方法(short)(a + 20)
a += 20; // 通过编译,正常运行
也就是说,我们平时写代码的时候尽量使用+=这样的对变量本身赋值的操作来代替表达式。
逻辑与(&)和短路与(&&)
- 逻辑与(&):无论左边真假,右边都要执行。
- 短路与(&&):如果左边真,右边执行;如果左边假,右边不执行。
同理逻辑或(|)和短路或(||)的关系,这也就解释了为什么我们平时在条件判断的时候多数使用“&&”和“||”而不是“&”和“|”。
两个数组指向相同内存
arr把地址给了arr2,两个数组指向同一个内存空间。此时两个数组任意一个发生变化,另一个会同时变化。
对象内存图
- 单个对象
- 多个对象
- 多个对象指向相同
this关键字
this:代表所在类的对象的引用。方法在哪个对象被调用,this就代表那个对象。
什么时候用? 解决局部变量隐藏成员变量的问题。
String对象
- new和赋值创造对象在内存上的区别。
- 字符串比较
==的比较,如果是基本数据类型,比较的是数值;如果是引用类型,比较的是地址是否相同。
这里字符串是引用类型,想比较数值大小需要使用equals()方法。
StringBuilder
- 如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费内存空间,而这种操作还不可避免。那么有没有一种比较好的方式可以解决这个问题呢?
答案是肯定的,我们可以通过Java提供的StringBuilder类就来解决这个问题。
StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器。这里的可变指的是StringBuilder对象中的内容是可变的,String内容是不可变的。
- 构造方法
//public StringBuilder(): 创建一个 空白可变字符串对象,不含有任何内容
StringBuilder sb = new StringBuilder();
System.out.print1n("sb:" + sb);
System.out.print1n("sb. length();" + sb.1ength());
//public StringBuilder(String str). 根据字符串的内容,来创建可变字符串
StringBuilder sb2 = new StringBuilder( "hel1o");
System.out.print1n("sb2;" + sb2);
System.out.println("sb2.1ength():" + sb2. length());
- 常用方法append和reverse
StringBuilder sb = new StringBuilder();
//public StringBuilder append(任意基本类型)添加字符串,返回对象本身
// StringBuilder sb2 = sb.append("java");
// System.out.println(sb); java
// System.out.println(sb2); java
// System.out.println(sb == sb2); true
//常用操作字符串尾添加,由于是对象本身的值变化,不需要接收返回值
sb.append("java");
sb.append("helloWorld");
sb.append(100);
sb.append('w').append((byte)2).append(100L);
System.out.println("sb: " + sb);
//public StringBuilder reverse()返回相反的字符串序列
sb.reverse();
System.out.println("sb: " + sb);
- String和StringBuilder相互转换
StringBuilder转换为String:public String toString() 通过toString()就可以实现把StringBuilder转换为String
String转换为StringBuilder:public StringBuilder(String s) 通过构造方法就可以实现把String转换为StringBuilder
ArrayList
- 构造和添加元素
//public ArrayList()构造一个空的集合对象
//ArrayList<String> arrayList = new ArrayList<>();
ArrayList<String> arrayList = new ArrayList<String>();
//public boolean add(E e)将指定元素添加到集合末尾
arrayList.add("hello");
arrayList.add("world");
arrayList.add("java");
//public void add(int index, E element)将指定元素添加到指定位置
arrayList.add(1, "javaSE");
System.out.println(arrayList);
- 常用方法
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
//public boolean remove(Object o): 删除指定的元素,返回删除是否成功
//System.out.println(array.remove("world"));
//public E remove(int index): 删除指定索引处的元素,返回被删除的元素
//System.out.println(array.remove(1));
//public E set(int index,E element): 修改指定索引处的元素,返回被修改的元素
System.out.println(array.set(1, "javaee"));
//public E get(int index): 返回指定索引处的元素
System.out.println(array.get(0));
System.out.println(array.get(1));
System.out.println(array.get(2));
//public int size(): 输出集合元素数量
System.out.println(array.size());
System.out.println(array);
继承
this和super
this和super在用法上很相似。this访问本类的成员变量和方法,super访问父类的成员变量和方法。
class Fu {
public int age = 40;
}
class Zi extends Fu {
public int age = 20;
public void show() {
int age = 30;
//访问方法中变量
System.out.println(age);
//访问类中成员变量
System.out.println(this.age);
//访问父类的成员变量
System.out.println(super.age);
}
}
继承中构造方法的访问
class Fu {
public Fu() {
System.out.println("父类的无参构造");
}
public Fu(int age) {
System.out.println("父类的有参构造");
}
}
class Zi extends Fu {
public Zi() {
System.out.println("子类的无参构造");
}
public Zi(int age) {
System.out.println("子类的有参构造");
}
}
public class Main {
public static void main(String[] args) {
Zi zi = new Zi();
//output:
//父类的无参构造
//子类的无参构造
Zi zi1 = new Zi(20);
//output:
//父类的无参构造
//子类的有参构造
}
}
子类中所有的构造方法默认都会访问父类中无参的构造方法为什么呢?
- 因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化前,一定要先完成父类数据的初始化。
- 每一个子类构造方法的第一条语句默认都是:
super();
如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?
- 通过使用super关键字去显示的调用父类的带参构造方法
- 在父类中自提供一个无参构造方法
继承中成员方法的访问
先访问子类中的方法,子类中没有访问父类,都没有报错。相较于构造方法没有默认的super,当然也可以人为super.function();
调用父类方法。
super内存图
多态
多态的访问特点
什么是Java中的多态?同一对象的不同种状态,猫可以是猫,也可以是动物。
public class Main {
public static void main(String[] args) {
Animal animal = new Cat();
System.out.println(animal.age);//output: 40
//System.out.println(animal.weight); 过不了编译
animal.eat();//output: 猫猫吃东西
//animal.play(); 过不了编译,因为Animal这个类没有play方法
}
}
class Animal {
public int age = 40;
public void eat() {
System.out.println("动物吃东西");
}
}
class Cat extends Animal {
public int age = 20;
public int weight = 100;
@Override
public void eat() {
System.out.println("猫猫吃东西");
}
public void play() {
System.out.println("猫猫玩耍");
}
}
- 成员变量:编译看左边,运行看左边
- 成员方法:编译看左边,运行看右边
- 原因:成员方法有重写,成员变量没有
多态的优缺点
优点,使用父类型作为参数,可以使用具体子类型的重写方法;缺点,不能使用子类所有的方法(使用向下转型解决)。
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
whoEat(cat);//猫猫吃东西
whoEat(dog);//狗狗吃东西
}
public static void whoEat(Animal a) {
a.eat();
}
//如上同理继承Animal类
class Dog extends Animal {
public int age = 20;
public int weight = 100;
@Override
public void eat() {
System.out.println("狗狗吃东西");
}
}
多态转型
- 向上转型:从子到父,父亲引用指向子类对象
- 向下转型:从父到子,父亲引用转为子类对象
Animal animal = new Cat();//向上转型
Cat c = (Cat)animal;//向下转型