学习资料:b站尚学堂Java300
目录
【尚学堂】Java300集零基础适合初学者视频教程_Java300集零基础教程_Java初学入门视频基础巩固教程_Java语言入门到精通_哔哩哔哩_bilibili
主要是记录一些容易混淆或者是比较重要的细节和知识点
先把之前的手写笔记直接拿过来, 再敲一遍太麻烦了
手写笔记
对象创建
创建对象的四步:
- 分配对象空间, 并将对象成员变量初始化为0或空
- 执行属性值的显式初始化
- 执行构造方法
- 返回对象的地址给相关的变量
静态导入:导入指定类的静态属性和静态方法
import static java.lang.Math.*; //导入Java类的所有静态属性
import static java.lang.Math.PI; //导入Math类的PI属性
final修饰的变量赋值有三种方式:
- 定义时赋值且不可改变
- 构造方法中赋值
- 类静态代码块中赋值
静态初始化块, 最先运行, 先于构造方法, 但是程序运行不管创建几个对象都只会运行一次
static{
System.out.println("Initialize the class");
school = "CCNU";
showSchool(); //静态初始块内可调用静态方法
}
子类创建对象时即使没有调用父类的构造方法, 父类的静态初始化块仍然会运行
子类不继承父类的构造方法但是会调用, 子类的任何构造函数第一行代码如果没有显式调用super(..)或者this(..), 那么java默认都会调用super(), 即调用父类的无参构造方法, 这里的super()可以省略
关于重写
子类重写与重载的区别:
子类的同名方法如果参数列表与父类方法不一致可以看成重载, 返回值类型就可以不同, 如果同名方法的参数列表一致则需要遵循重写相关规则, 返回值类型不可随意变更
子类无法重写父类的静态方法, 当父类为static方法时子类重写也必须是static方法, 这样编译不会报错, 但是实际上也并没有对父类静态方法进行重写, 父类对象为子类对象的向上转型时调用的仍然是父类的静态方法, 而非静态重写函数则在此种情况下调用的是子类的方法
public void show(){} //报错,子类无法重写父类同名静态方法
public static void show() { //子类同名静态方法会覆盖(不是重写和重载,即子类父类同名方法独立存在,各调用各的)父类静态方法
System.out.println("Show Student");
} //不报错, 但是并没有重写父类方法
重写equals方法
- 重写equals方法时传入的形参一定是Object类
- 重写equals方法时一定也要重写hashCode方法, 这样可以避免使用Set和Map时出现问题
重写equals方法时看情况来选择使用instanceof还是getClass()方法, 前者可比较子类, 后者只能同类比较
public boolean equals(Object o){
if (this == o) return true;
// if (o == null || getClass() != o.getClass()) return false;
// Person person = (Person)o;
// return id == person.id && name.equals(person.name);
if (o instanceof Person){
Person person = (Person)o;
return person.id == id && person.name == name;
}
return false;
}
Object类的默认toString()方法返回的是类名@地址
多态(polymorphism)
多态的存在是为了满足程序的灵活性, 有了多态之后就可以用父类一个接口来调用任意个子类的方法, 而不需要对同名方法针对各个子类进行重载, 多态需要满足下面三个条件:
- 继承
- 方法重写
- 父类引用指向子类对象
package com.kiddy.test;
public class Animal {
static void shout(Animal animal){
animal.shout();
}
void shout(){
System.out.println("Animal is shouting");
}
public static void main(String[] args){
Animal animal = new Animal();
Animal tiger = new Tiger();
Animal lion = new Lion();
shout(animal);
shout(tiger);
shout(lion);
animal.shout();
tiger.shout();
lion.shout();
}
}
class Lion extends Animal{
void shout(){
System.out.println("Lion is shouting");
}
}
class Tiger extends Animal{
void shout(){
System.out.println("Tiger is shouting");
}
};
抽象类和抽象方法
抽象方法: 使用abstract修饰的方法, 没有方法体只有声明. 定义的是一种规范, 就是告诉子类必须要给抽象方法提供具体的实现
抽象类: 包含(一个以上)抽象方法的类就是抽象类, 通过抽象类就可以做到严格限制子类的设计, 使子类之间更加通用
注:抽象类不能实例化, 不能够new. 抽象类可以包含属性, 方法, 构造方法. 但是构造方法不能用来new实例, 只能用来被子类调用.
package com.kiddy.test;
public abstract class Move {
private String name;
abstract void move(); //抽象方法不能有方法体
public void setName(String name){
this.name = name;
}
public String getName() {
return name;
}
public static void main(String[] args) {
Move move = new Dog();
move.move();
}
}
class Dog extends Move{
@Override
void move() { //父类的抽象方法必须实现
setName("Dog");
System.out.println(getName() + " is running");
}
}
接口
接口是比抽象类还抽象的抽象类, 抽象类还提供某些具体实现, 接口不提供任何实现, 所有方法都是抽象方法. 接口可以更加规范地对子类进行约束, 全面而专业地实现了规范和具体实现的分离. 生产活动中往往使用"面向接口"的思想来设计系统. 接口与实现类不是父子关系, 是实现规则的关系
接口声明格式:
[public] interface Name [extends Father1, Father2...] {
[public static final] VarType name; //常量定义
[public abstract] VarType function();
}
上述格式适用于jdk1.8之前, 之后的版本接口中可以包含普通的静态方法和默认方法
jdk8以后可以在接口中定义默认方法和静态方法
用default修饰的方法就是默认方法, 默认方法需要模板的实现类对象来调用
接口可多继承, interface A extends B, C那么实现类就需要实现ABC里声明的所有方法
public interface Action {
void move();
default void fun1(){
System.out.println("默认方法");
fun2(); //接口的默认方法可以调用静态方法
}
public static void fun2(){
System.out.println("接口内静态方法");
} //接口内的静态方法
}
interface Eat{
void eat();
}
class Bird implements Action, Eat{
@Override
public void move(){
System.out.println("Birds fly");
}
public static void main(String[] args) {
Bird bird = new Bird();
bird.move();
bird.eat();
// Eat eat = (Eat)bird;
// eat.eat();
bird.fun1();
Action.fun2(); //直接调用接口的静态方法
Action a2; //接口类型的引用是可以的
}
@Override
public void eat() {
System.out.println("Birds eat");
}
}
String类
public static void main(String[] args) {
String str1 = "abcde";
String str2 = "abcde";
String str3 = new String("abcde");
System.out.println(str1 == str2); //true
System.out.println(str1 == str3); //false
}
这里str1与str2都指向同一个常量池地址, 而str3的地址则是一个String类对象地址
String类常用操作:
package com.kiddy.test;
public class TestString {
public static void main(String[] args) {
String str1 = "abcde";
String str2 = "ABcDEAB";
System.out.println(str1.equals(str2));
System.out.println(str1.equalsIgnoreCase(str2)); //equalsIgnoreCase方法无视大小写比较字符串是否相同
System.out.println("" + str1.charAt(0) + str1.charAt(str1.length()-1)); //空字符串一定要加在最前面, 不然输出的是数字
System.out.println(str1.indexOf("bc")); //从头开始找匹配字符串的位置
System.out.println("abcdabc".lastIndexOf("abc")); // 从后往前找匹配子串的位置
System.out.println(str2.replace("AB", "12")); //字符串替换
System.out.println(str2.startsWith("ABC")); //判断是否以特定字符串开头
System.out.println(str2.endsWith("AB")); //判断是否以特定字符串结尾
System.out.println("01234567".substring(0, 4) + " | " + "01234567".substring(4)); //字符串切片
System.out.println(str1.toUpperCase()); //全部转大写
System.out.println(str2.toLowerCase()); //全部转小写
System.out.println(" 12 3 ".trim()); //删除头尾空格
System.out.println(" 12 3 ".trim().replace(" ", "")); //删除所有空格
}
}
false
false
ae
1
4
12cDE12
false
true
0123 | 4567
ABCDE
abcdeab
12 3
123
进程已结束,退出代码为 0
内部类
内部类是为了解决封装问题, 使同一个包的类不能直接调用内部类, 而需要通过外部类来访问内部类
内部类可分为成员内部类(静态、非静态)、匿名内部类(一次性使用)、局部内部类
package com.kiddy.test;
/**
* 测试各种内部类
*/
public class TestInner {
static{
System.out.println("*******");
}
int a = 0;
static float b;
void subtest(A a) {
Inner2.showInner2();
a.fun1();
a.fun2();
}
void subtest2(B b){
b.fun();
}
public class Inner{ //非静态内部类不能有static方法和变量
int a = 3;
void subtest(){
System.out.println("Inner.subtest");
}
void showInner(){
System.out.println("Inner.showInner");
System.out.println(this.a);
System.out.println(TestInner.this.a); //访问外部类属性
subtest();
TestInner.this.subtest(new A() { //匿名类继承接口
@Override
public void fun1() {
System.out.println("Inner.subtest.fun1");
}
@Override
public void fun2() {
System.out.println("Inner.subtest.fun2");
}
}); //访问外部类方法
subtest2(new B(){ //匿名类继承父类
void fun(){ //重写父类方法
System.out.println("匿名类的方法");
}
});
}
}
static public class Inner2{
static void showInner2(){
System.out.println("Inner2.showInner2");
System.out.println(b); //静态内部类只能访问外部类的静态成员
}
}
public static void main(String[] args) {
// TestInner.Inner inner = new TestInner().new Inner();
Inner inner = new TestInner().new Inner();
inner.showInner();
}
}
interface A{
void fun1();
void fun2();
}
class B{
void fun(){
System.out.println("B的方法");
}
}
*******
Inner.showInner
3
0
Inner.subtest
Inner2.showInner2
0.0
Inner.subtest.fun1
Inner.subtest.fun2
匿名类的方法
进程已结束,退出代码为 0