一、数据类型
- 基本类型
- 整型(4个): byte(字节型)、short(短整型)、int(整型)、long(长整型)
- 浮点型(2个):float(单精度型/浮点型) 、double(双精度型)
- 字符(1个): char(字符型)
- 布尔类型:(1个): boolean(布尔类型)
- 包装类型(引用数据类型)
- 基本数据类型的引用封装:Boolean、Byte、Character、Short、Lnteger、Long、Float、Double
- 区别:
- 基本数据类型直接将值放在栈中;
包装类型是把对象放在堆中,然后通过对象的引用来调用他们 ; - 初始值不同:
int的初始值为 0 、 boolean的初始值为false ;
包装类型的初始值为null ; - 使用场景:集合的基本类型需要是包装类型List<Integer> li = new ArrayList<>();
- 基本数据类型直接将值放在栈中;
- 转换(即装、拆箱):
- 自动装箱/拆箱是Java 编译器提供的原始类型和它的包装类之间转化的功能
- list.add(int Value); //编译器会自动执行int->Interger
- 自动装箱/拆箱是Java 编译器提供的原始类型和它的包装类之间转化的功能
- 区别:
- 数组
- 初始化:
- (略写)int[] arr = {1,2,3,4,2,3134,123};
- int[] arr=new int[10]
- a = new int[]{1, 2, 3, 4, 5};
- int[] arr = null;
- sout(arr):打印地址
- 初始化:
- 集合
- 与数组的区别
- 数组:定长、可以存放基本数据类型、引用数据类型
- 集合:自动扩容、只能存放引用数据类型和转化为包装类的基本数据类型
- 创建
- import java.util.ArrayList;
- ArrayList<String> list = new ArrayList<>();
- 方法
- 增:list.add("aaa");
- 删:
- 值:list.remove("aaa");//只找到第一个删除
- 索引:String c = list.remove(0);
- 改:String res = list.set(1,"d1d");
- 查:String s = list.get(0);
- 与数组的区别
- String字符串
- 创建
- 储存在堆区:String str = new String("asd")
- 直接赋值会复用栈区字符串常量池(串池)中的:String str = “asd”
- 编译时触发了字符串的优化机制,同上:String str = “a” +"b"+"c"
- String s2 = s1 + “b”:先创建堆区StringBuilder对象,再通过append方法,最后Tostring()返回堆区String对象
- 与字符数组的转换
- char[] carr = str.toCharArray();//用字符串创建字符数组
- String strlast = new String(carr);//用字符数组创建字符串
- 方法
- 截取:substring(开始, 终止)
- 全局替换:replace("AB"(可以是字符、字符串),"Q")
- 字符串比对:Str.equals(Str2); 返回1:相同;返回0:不相同
- ==:基本数据类型比较值、引用数据类型比较地址
- 创建
- StringBuilder内容可变(拼接与翻转)
- 使用连加时不需要创建新的对象(String底层也是通过StringBuilder进行字符串拼接)
- 创建:空参构造: new StringBulider()
- 方法
- 追加:append(任意类型)
- 翻转:reverse()
- 长度: len
- 内存原理:最开始是一个长度为16的字节数组,添加的内存小于16直接存,大于16则扩容(2*16+2 = 34)超过则以实际为准,(容量:sb.capacity()、长度:sb.length())
- StringJoiner(方便指定开头、结尾、分隔)
- 1.StringJoiner sj = new StringJoiner("---");
- 2. new StringJoiner("spe","begin","end");
- sj.add("");
- toString()
- 基本数据类型的引用封装:Boolean、Byte、Character、Short、Lnteger、Long、Float、Double
- 自动转换和强制转换
- 自动转换
- 总结:小容量转大容量
-
//1.多个类型数据混合运数时,系统会按最大的类型进行转换 int a = 10; //float a1 = a + 1.1; //错误 结果类型一个是double float a2 = a + 1.1F; //结果类型一个是float double a3 = a + 1.1; double a3 = a + 1.1; //结果类型一个是double //2.容量大的赋值给容量小的肯定会报错 //int b = 1.1; //错误 原因:double -> int //3.(byte,short) 和 char之间不会相互自动转换 byte b1 = 10; //正确 int b2 = 1; //byte b3 = b2; //错误 原因:变量赋值,判断该类型 //char c1 = b1; //错误 原因:byte不能自动转换为char //4.byte,short,char该三个数据类型计算,计算时首先转换为int类型 byte c1 = 1; short c2 = 2; //short c3 = c1 + c2; //错误 原因:计算时首先转换为int类型 int c3 = c1 + c2; //正确
- 强制转换
- 总结:大容量转小容量
//1.精度降低或溢出 int i = (int) 1.9; //结果 1 //2.强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级 //int x = (int) 10 * 3.5 + 6 * 1.5;//编译错误 int x = (int) (10 * 3.5 + 6 * 1.5);//正确 (int)44.0 -> 44 //3.char类型可以保留int的常量值,不能保存int的变量值需要强转 char c = 100; //保留int的常量值 int i = 100; //char m = i; //错误 char m = (char) i; //正确
- 隐式转换
-
在变量的初始化时,整数的默认类型是 int。byte b = 123; 123 默认是 int 类型,他会隐含强制转换为低级别的 byte 和 short 类型,所以不用显示强制转换;但是 int 类型只能显式强制转换为 long 型,所以 long a = 123L
浮点型不存在这种情况,因为在定义 float 类型时必须在数字后面跟上 F 或者 f
-
- 总结:大容量转小容量
- 自动转换
二、面向对象初阶
- Javabean类
- toString()函数会使得打印e的时候不打印地址值,而打印对象属性!
- 空参,全参构造
- static
- 静态变量:所有的对象共享(堆-静态区)
- 静态方法:常用在测试类、工具类(Math)
- )静态方法只能访问静态成员,非静态方法可以访问所有成员,静态方法中没有this关键字
- )因为main是静态的,所以测试类的其他函数都要是静态的
- ))main函数参数的用法:public static void main(String[] args) {
System.out.println(args.length);
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
} - ))program argument
- ))main函数参数的用法:public static void main(String[] args) {
- native
- native关键字:方法体是C或者汇编写的:public final native Class<?> getClass();
三、继承
Java超详细讲解类的继承_java_脚本之家 (jb51.net)
继承:Java只支持单继承(区别于C++的多继承)extends Base
- 任何类都会直接或间接extends Object
- 可以继承哪些内容
- 构造(都不能继承)
- 成员变量(非私有能被继承)
- 成员方法(static可以被继承、final可以被继承、private不能被继承)
- 访问特点
- 成员变量/方法寻找:就近原则
- name(从局部位置开始往上找)
- this.name(从本类成员位置开始往上找)
- super.name(从父类成员位置开始往上找)
- super.super.name(报错)(如果需要访问爷爷辈的成员变量、可以在父类定义访问爷爷变量的函数、子类调用)
- 成员变量/方法寻找:就近原则
- 重写(覆盖)
- 重写注解(JVM会检查语法):@override
- 本质:覆盖虚方法表的方法(非final、static、private)
- 名称、形参列表要一样、访问权限大于等于父类
- staticfun()可以在子类被重写,也可以通过子类的类名访问到父类的静态方法
- privatefun()在子类写同名函数不会报错!但是本身就没有继承,谈不上重写
四、多态
- 本质:父类引用指向子类对象:
- Animal a = new Dog();
- 多态·调用成员的特点
- 变量调用:编译看左边、运行看左边
- sout(a.name); //打印的是动物的名字
- 方法调用:编译看左边、运行看右边
- 本质:如果子类对方法进行了重写,在虚方法表中会把父类的方法进行覆盖
- 传入的对象可以是所有的子类,体现了多态的扩展性和便利
- stringbuilder.append(object obj);//任意对象都可以传入
- 不能使用子类的特有功能
编译看左边!父类没有的方法或变量(子类独有)编译会报错- 解决方法:类型转换:
- 能够调用子类的独有功能
if(a instanceof Dog){ Dog d = (Dog)a; d.d_fun();//Dog独有的功能 } if(a instanceof Dog d){ d.d_fun();//Dog独有的功能 }
- 能够调用子类的独有功能
- 解决方法:类型转换:
- 变量调用:编译看左边、运行看左边
五、 包、final、访问权限、代码块
- 包(package):文件夹,方便后期代码维护
- packagename.Student (全类名、限定类目)
- import packagename.Student(导包)
- 导包的情况分析
- ①使用同一个包的时候,不需要导包
②使用java.lang包中的对象,不需要导包
③其他情况都要导包
④如果同时使用两个包中的同名类,需要用全名
- ①使用同一个包的时候,不需要导包
- final(最终、不能被改变)关键字
- ①修饰方法:最终方法,不能被重写【是一种规则,不希望被改变】
- ②修饰类:最终类,不能被继承【所有的类方法都不希望被重写】
- ③修饰变量:叫做常量,只能赋值一次(创建必须赋值)
public final native Class<?> getClass(); public final native void notify(); public final class String
- 访问权限
- private > 空着不写 > protected > public
- private int age(只能在自己的类中使用)
- int age(同一个包中能使用)
- protected(不同包的子类能使用)
- pubulic(不同包下的无关类可以使用)
- 实际开发中一些规则(一般只用private、public)
- 成员变量(私有)
- 方法(公开)
- 特例:抽取其他方法共性方法,表示规则(私有)
- private > 空着不写 > protected > public
- 代码块
- *局部代码块({})【写在方法中的代码块】:变量只在所属的代码块有效,使得变量能提前结束,节约内存的技术
- *构造代码块({})【写在成员变量位置】:执行时机:每次构造之前
- 静态代码块({static{})【写在成员变量位置】随着类的加载而加载、只执行一次
//以下的静态代码块用于数据的初始化 class Student{ static ArrayList<user> list = new ArrayList<>(); static{ list.add(new user("zs",20)); } }
六、抽象类与接口
- 抽象类与抽象方法(意义:强制子类必须按照这种格式进行重写,达到规范作用)
- 抽象类:只有被继承才能被实例化:public abstract class Person
- 抽象方法:有抽象方法的类必须为抽象类、没有方法体,类似纯虚函数:public abstract void work();
- 特性
- 不能实例化
- 抽象类中不一定有抽象方法,有抽象的方法一定是抽象类
- 抽象的子类:要么重写所有的抽象方法、要么是抽象类
- 对行为、规则的抽象:接口
- 场景:部分子类用的到相同的规则性方法(swim())
- 特性:接口的子类(实现类)要么重写接口中的所有抽象方法、要么是抽象类
- 接口成员:
- 接口成员变量(常量):public static final(默认修饰)
- 接口成员方法
- ①public abstract void fun() 纯虚方法
- ②public default void show(){} 默认方法有方法体、可以不被重写、如果冲突就必须重写
- ③private void log(){} 定义私有方法供接口内部使用
- ④public static void show(){} 静态方法;唯一调用方法:Inter.static_show();(对比类的静态方法:可以被子类或者被实例调用)
- 接口的多态
- 接口名称作为函数参数:接收所有的实现类对象)
- 接口类型 j = new 实现类对象():遵循编译看左边,运行看右边
- 适配器模式(接口有太多的抽象方法,都需要重写,但是用不到)
- 解决方法:中间加一个虚拟类空实现所有接口方法,然后继承这个虚拟类,就只用重写所需要的接口方法了
- 如果类需要继承父类,可以让中间类代为继承
public interface 接口名{
public abstract void swim();//没有体
}
public class 类名 extends 父类 implements 接口名1,接口名2{
}
【中间类(适配器)】
public abstract class XXXAdapter implements XXX{
@override
……
}
pulic class Classname extends XXXAdapter {}
七、内部类
- 类的五大成员
属性
方法
构造
代码块
内部类 - 四种内部类:
- ①成员内部类【定于在成员位置的类】
- 创建:Car.Engine ce = new Car().new Engine();
- 关于权限:private不能在外界创建,只能在类内创建、protected本包和(其他包)子类
- 关于内存:当外部类被实例化后,才会生成独立的内部类字节码文件(.calss);内部类有一个隐含的Outer.this成员,存储外部类的地址值,这就是为什么内部类可以访问外部类的成员变量
- 调用成员内部类方法:
- 调用成员内部类的非静态方法:new Outer().new Inner().fun()
- 调用成员内部类的静态方法:new Outer().Inner.Statcfun()
- 使用(见段尾代码)
- ②静态内部类(成员内部类的一种)
- 创建:Outer.Inner oi = new Outer.inner()
- 关于内存:静态class字节码编译时就有,不需要等到有外部类对象才能创建
- 调用静态内部类方法:
- 调用静态内部类的非静态方法(需创建):new Outer().inner.staticfun()
- 调用静态内部类的静态方法(无需创建):Outer.staticInnter.staticfun()
- 访问外部类成员:只能访问静态成员、访问非静态成员可以创建外部类对象。
- ③局部内部类(没什么用)
- 将内部类定义在方法里面的就是局部内部类,类似局部变量
- 外部无法直接使用(活动范围仅限函数中)
- 可以访问局部变量与外部类成员变量
- ④匿名内部类(对象):用于单次使用、为此创建一个类显得麻烦,因此用匿名内部类
- 利用接口实现关系创建:new 接口名{……}
- 利用父类继承关系创建:new 父类名{……}
- 思路:如果想要传入一个虚拟类(接口),必须继承实现虚拟方法,匿名内部类提供了一个在当下直接重写的方法
- ①成员内部类【定于在成员位置的类】
// 成员内部类的定义形式
public class Car{
String carName;
int carAge;
class Engine{
String engineName:
int engineAge;
}
}
//私有:定义方法供外部获取实例、用Object接收(多态)
public Engine getEngineInstance(){
return new Engine();
}
Object inner = getEngineInstance() //不能使用它的方法
//案例:用接口接收,使得可以使用接口中的方法(接口的多态)
class ArrayList{
public Iterator<E> iterator{
return new Itr();//返回的的类型是接口的类型,多态的概念
}
private class Itr implements Iterator<E>
}
//匿名内部类使用方法:
method(
new Animal(){
@override
public void eat(){
sout("狗吃骨头")
}
};
)
八、补充
字符串string操作
// 字符串向数组转化
byte b[] = str1.getBytes();
// 获取字母下标
str1.indexOf("c");
str1.indexOf("c",3); // 第三个c
// 字符串截取
str1.substring(6) //6-》
str1.substring(0,5) //0-》4
// 大小写转化
str1.toUpperCase() // 大写
str1.toLowerCase() // 小写
// 字符串比对
str1.equals(str2)
str1.equalsIgnoreCase(str2) // 不区分大小写
// 替换
str.replaceAll("l","x") //l->x
代码块的补充
public class Qiuyu{
public static void main(String args[]){
// TODO Auto-generated method stub
{
int x = 30 ;
System.out.println("普通代码块 --> x = " + x) ;
}
int x = 100 ;
System.out.println("代码块之外 --> x = " + x);
}
};
new Demo() ;
new Demo() ;
new Demo() ;
单例模式(初级)
class Singleton{
static Singleton instance = new Singleton() ;
private Singleton(){
}
public void print(){
System.out.println("Hello World!!!") ;
}
};
public class Qiuyu{
public static void main(String args[]){
// TODO Auto-generated method stub
Singleton s1 = null ;
s1 = Singleton.instance ;
s1.print() ;
}
};
对象数组
Person per[] = new Person[3] ;
链表
P153例5.77节点类代码如下:
class Node{
private String data ;
private Node next ;
public Node(String data){
this.data = data ;
}
public void setNext(Node next){
this.next = next ;
}
public Node getNext(){
return this.next ;
}
public String getData(){
return this.data ;
}
};
public class Qiuyu{
public static void main(String args[]){
// TODO Auto-generated method stub
Node root = new Node("火车头") ;
Node n1 = new Node("车厢-A") ;
Node n2 = new Node("车厢-B") ;
Node n3 = new Node("车厢-C") ;
root.setNext(n1) ;
n1.setNext(n2) ;
n2.setNext(n3) ;
printNode(root) ;
}
public static void printNode(Node node){
System.out.print(node.getData() + "\t") ;
if(node.getNext()!=null){
printNode(node.getNext()) ;
}
}
};