1 .StringBuilder
-
一个可变的字符序列。
-
但不保证同步。
可以将StringBuilder看成是一个容器,这里的可变指的是StringBuilder对象的内容是可变的。
1.1 StringBuilder和String的区别
String : 内容是不可变的
StringBuilder : 内容是可变的
1.2 StringBuilder 的构造方法
-
-
StringBuilder()
构造一个没有字符的字符串构建器,初始容量为16个字符。StringBuilder(int capacity)
构造一个没有字符的字符串构建器,由capacity
参数指定的初始容量。StringBuilder(String str)
构造一个初始化为指定字符串内容的字符串构建器。
-
1.3 StringBuilder的常用方法
-
-
StringBuilder
append(int i)
将int
参数的字符串表示法附加到此序列。StringBuilder
append(long lng)
将long
参数的字符串表示法附加到此序列。StringBuilder
append(Object obj)
追加Object
参数的字符串Object
形式。StringBuilder
append(String str)
将指定的字符串附加到此字符序列。
-
-
-
StringBuilder
insert(int offset, String str)
将字符串插入到此字符序列中。int
lastIndexOf(String str)
返回指定子字符串最右边出现的字符串内的索引。int
lastIndexOf(String str, int fromIndex)
返回指定子字符串最后一次出现的字符串中的索引。
-
-
-
-
-
-
String
substring(int start)
返回一个新的String
,其中包含此字符序列中当前包含的字符的子序列。String
substring(int start, int end)
返回一个新的String
,其中包含此序列中当前包含的字符的子序列。String
toString()
返回表示此顺序中的数据的字符串。void
trimToSize()
尝试减少用于字符序列的存储。public static void main(String[] args) { //StringBuilder对象的创建 底层本质依然是字节数组 StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(32);//构建一个容量为32的字节数组 StringBuilder sb3 = new StringBuilder("abcdef"); sb1.append("abc").append(123).append(true);//链式编程 String str = sb1.toString(); System.out.println(str); System.out.println(sb1.length()); sb1.insert(3,"hello"); System.out.println(sb1.toString()); System.out.println(sb1.reverse().toString());//字符串的反转 逆序 sb1.setCharAt(0,'A'); System.out.println(sb1.toString());// 修改指定位置的字符 }
1 实现一个将String和Stringbuilder两个对象之间的相互转换
1 将StringBuilder 转换为String
String
toString()
返回表示此顺序中的数据的字符串。2 将String转换为StringBuilder
StringBuilder(String str)
构造一个初始化为指定字符串内容的字符串构建器。2 StringBuilder和String的使用场景
如果只是单纯的使用到一个字符串,则直接使用String
如果字符串的内容是需要动态改变(动态拼接)则是用Stringbuilder
StringBuffer 和Stringbuilder的区别:
Stringbuffer 线程同步的 线程安全的
Stringbuilder线程不同步 线程不安全的
在一般情况下 使用StringBuilder ,在多线程环境下 进行字符串的拼接操作 此时就需要考虑使用StringBuffer
2.继承
是面向对象三大特征之一。
2.1 继承的格式:
public class 子类名 extends 父类名{ }
将继承了其他类的类 称为子类 派生类 衍生类
被继承的类 称为父类 超类 基类
2.2 继承中子类的特点:
1 子类可以继承父类非私有成员;
2 子类还可以有自己特有的成员
2.3 继承所产生的影响:
1 继承似的类与类之间产生了关系,父子类关系,产生父子类关系后,子类可以使用父类中非私有的成员。
2 子类继承了父类,就继承了父类的非私有的方法和属性
3 在子类中,可以使用父类中定义的方法和属性,也可以创建新的属性和方法
4 在java中,继承的关键字用的是extends 及子类不是父类的自己 而是对父类的"扩展"
public class Person { private String name; private int age; String county="中国"; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void eat(){ System.out.println("在餐厅用餐..."); } }
public class Student extends Person { String school = "中北大学"; public Student() { } public void study(){ System.out.println("努力敲代码....."); } }
public class Teacher extends Person{ public Teacher() { } public void teach(){ System.out.println("认真讲课...."); } }
public class ExtendsTest { public static void main(String[] args) { Student stu = new Student(); stu.setName("小明"); stu.setAge(18); System.out.println(stu.getName() +"--"+stu.getAge() +"--"+stu.county); stu.eat(); stu.study(); } }
2.4 继承规则
1 子类不能直接访问父类的私有的成员变量和方法
public class ExcentsDemo {//测试类 public static void main(String[] args) { Fu f = new Fu(); f.show(); Zi z = new Zi(); z.method(); z.show(); } } class Fu{ public void show(){ System.out.println("show方法被调用...."); } } class Zi extends Fu{ public void method(){ System.out.println("method方法被调用"); } }
2.5 继承的好处和弊端
好处:
1 提高了代码的复用性
2 提高了代码的维护性
弊端:
继承使得类与类之间产生了关系,类的耦合性增强,当父类发生变化时,子类实现也不得不跟着变化,削弱了子类的独立性
开发的原则:高内聚 低耦合
什么时候使用继承?
继承体现的是一种关系:is a
继承的使用,一定是当两个类之间满足is a的关系的时候 才使用继承。不要为了继承而继承(不要仅仅为了减少代码的编写 ,提高代码的复用而去使用继承)
2.6 继承中变量的访问特点
public class ExcentsDemo {//测试类 public static void main(String[] args) { Fu f = new Fu(); f.show(); System.out.println(f.num);//10 Zi z = new Zi(); System.out.println(z.num);//20 z.method();//30 z.show(); } } class Fu{ int num = 10; public void show(){ System.out.println("show方法被调用...."); } } class Zi extends Fu{ int num = 20; public void method(){ int num = 30; System.out.println(num); System.out.println("method方法被调用"); } }
1 在java中 变量的使用遵循就近原则
2 在继承关系的类中,优先在子类的局部返回中找
3 子类的成员范围中找
4 父类的成员找
5 如果以上都没有(不考虑的父类的父类) 则报错。
2.7 super
super的用法和this用法相似:
1 this:代表本类的当前对象(代表本类对象的引用)
2 super :代表本类的父类对象(代表父类存储空间的标识(引用))
this:可以访问成员变量 访问成员方法 调用本类的其他构造方法
public int add(int a,int b){ return a+b; } public int add(int a,int b , int c){ return this.add(a,b) +c; }
super: 可以访问父类的成员变量 调用父类的成员方法 调用父类的构造方法
public Zi(){ super(); } public Zi(int num){ super(); this.num = num; System.out.println("子类的带参构造执行...."); }
构造方法调用,this和super不能同时出现。this和super调用构造方法 都必须出现在第一行
使用super去访问成员变量或者方法 成员变量或者成员方法 一定是子类和父类拥有同名的变量和方法的时候
2.8.继承中构造方法的访问特点
在子类的构造方法中,默认会调用父类的无参构造
为什么呢?
-
因为子类会继承父类中的数据,可能还会使用父类的数据,所以 ,子类初始化之前 一定要先使用父类的数据的初始化
-
每一个子类的构造方法中 第一条语句默认都是super();
-
如果父类中没有无参构造 会发生什么?
-
通过super区显式的调用父类的其他的带参构造
super(num);
-
在父类中提供一个无参构造
-
推荐:自己提供无参构造
-
2.9.继承中成员方法的访问特点
public class ExcentsDemo {//测试类
public static void main(String[] args) {
Fu f = new Fu();
f.show();//父类
Zi z = new Zi(10);
z.show();//子类的show
}
}
class Fu{
int num = 10;
public Fu(){
System.out.println("父类的无参构造执行....");
}
public Fu(int num){
}
public void show(){
System.out.println("父类的show方法被调用....");
}
public int add(int a,int b){
return a+b;
}
public int add(int a,int b , int c){
return this.add(a,b) +c;
}
}
class Zi extends Fu{
int num = 20;
int a ;
String str;
public Zi(){
}
public Zi(int num){
super(num);
this.num = num;
System.out.println("子类的带参构造执行....");
}
public Zi(int num , int a ,String str){
super(num);
}
public void method(){
int num = 30;
System.out.println(super.num);
System.out.println("method方法被调用");
}
public void show(){
System.out.println("子类的show 方法...");
}
}
通过子类对象访问子类和父类的同名方法:
-
子类的范围中找
-
父类范围找
-
如果都没有 就报错。
子类对父类的扩展:子类可以有自己的特有的成员变量和成员方法,子类中还可以定义和父类同名的成员变量和方法。
2.10 方法的重写
方法重写,子类中出现和父类中一模一样的方法的声明。
方法重写的应用场景:当子类需要父类的功能的时候,而父类的功能又不能满足子类的需求,在方法中 ,子类有自己的特点。
public class OverrindeDemo {;
public static void main(String[] args) {
Son s = new Son();
s.getMoney();
}
}
class Father{
public void getMoney(){
System.out.println("通过体力劳动来获取金钱....");
}
}
class Son extends Father{
@Override//方法重写的检测标记
public void getMoney(){
System.out.println("通过脑力劳动来获取金钱....");
}
}
方法重写的注意事项:
1 私有的方法不能被重写。
2 子类重写的时候 不能采用比父类给加严格的访问修饰符(pulic > default > private)
3 当父类中的方法为私有时,如果子类出现了和父类一模一样的方法的时候,此时这两个方法之间没有任何关系。
2.11.java中继承的注意事项
1 java中类的继承只支持单继承,不支持多继承。一个类只能有一个直接的父类
2 java中的类的继承支持多层继承 不支持多重继承
class A{
int a = 100;
}
class Father extends A{
void getMoney(){
System.out.println("通过体力劳动来获取金钱....");
}
}
class Son extends Father{
@Override//方法重写的检测标记
public void getMoney(){
System.out.println("通过脑力劳动来获取金钱....");
}
}
3 包
3.1 package
包: 本质就是文件夹,对类进行分类管理
包的命名格式: 包名采用多级格式,每一级之间使用.分割
一般情况下:包名采用公司域名的逆序:cn.lanqiao.模块名
3.2 导包(import)
String类位于java.lang包下,在使用String类的时候 不需要导包
凡是位于java.lang包下的类 在使用的时候都不需要导包。除此之外,其他的类在使用的时候,都需要进行导包操作
导包意义:
当一个类有包信息之后,此时类的类名就有了两种形式
全类名:包名.类名 java.util.Scanner
简单类名:类名 Scanner
导包的意义就在于,当我们在类的内部使用类的时候,可以直接使用类的简单类名来进行相应的操作
导包语法:import java.util.Scanner;
3.3.jdk的主要的包
java.lang 包含一些java语言的核心类 如:String Thread
java.awt 主要包含了一些图形化窗口相关操作的工具类
java.net 主要包含了一些和网络相关的操作
java.io 主要包含IO操作一些相关的类
java.util 主要包含的是一些使用的工具类
4.修饰符
4.1权限修饰符
修饰符 | 同一个类 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | ✔ | |||
默认不写【default】 | ✔ | ✔ | ||
protected | ✔ | ✔ | ✔ | |
public | ✔ | ✔ | ✔ | ✔ |
4.2状态修饰符
-
final(最终的)
-
static(静态)
4.2.1 final
final 是一个关键字 最终的意思,他可以修饰成员方法 成员你变量 类
final修饰的特点:
修饰方法: 修饰方法的时候 方法不能被重写
修饰变量:变量是常量,不能被再次赋值。只能被赋值一次
// public final int A =100;//在声明的同时赋值
public final int A ;
public A(){//使用构造方法来赋值
A = 100;
}
修饰类:类不能被继承
public final class A {
}
final修饰局部变量:
final修饰局部变量的时候 ,变量是基本类型,变量的值不能改变。
final修饰引用类型的局部变量
public static void main(String[] args) {
final Student stu = new Student();// 自定义引用类型的变量
stu.setName("张三");
stu.setAge(24);
System.out.println(stu.getName()+"---"+stu.getAge());
// stu= new Student(); 这个是不允许
stu.setName("李四");//这个可以允许修改
stu.setAge(26);
System.out.println(stu.getName()+"---"+stu.getAge());
}
final修饰的是引用类型的地址值是不能发生改变,但是引用地址指向的对象的属性却是可以改变的
4.2.2.static
static的意思是静态,可以修饰成员方法 成员变量
适用范围:
在java类中,可以使用static修饰属性,方法,代码块,内部类
被修饰的成员的特点:
1 随着类的加载而夹在
2 优先于对象存在
3 修饰的成员 被所有对象共享
4 访问权限允许时,可以不创建对象,直接被类调用,调用时可以使 类名.
public static void main(String[] args) {
Student stu1 = new Student();// 自定义引用类型的变量
stu1.setName("张三");
stu1.setAge(24);
//为static修饰的变量赋值 推荐使用类名.的形式访问
Student.university ="中北大学";
System.out.println(stu1.getName()+"---"+stu1.getAge()+"--"+Student.university);
Student stu2= new Student();
stu2.setName("李四");//这个可以允许修改
stu2.setAge(26);
Student.university ="青岛大学";
System.out.println(stu2.getName()+"---"+stu2.getAge()+"--"+Student.university);
Student stu3= new Student();
stu3.setName("王五");//这个可以允许修改
stu3.setAge(22);
System.out.println(stu3.getName()+"---"+stu3.getAge()+"--"+Student.university);
}
static的访问特点;
public class A {
int a = 100;//非静态成员变量
static int b =200;//静态成员变量
public static void main(String[] args) {//
// show(); 静态方法不能直接调用非静态方法
A a = new A();//在静态方法中 如果要访问非静态的成员 必须通过对象来访问
a.show();
int aa = a.a;
print();
}
public void show(){//非静态方法
System.out.println(a);//
System.out.println(b);
}
public static void print(){//静态方法
// System.out.println(a);
System.out.println(b);
}
}
非静态成员方法:
-
能访问静态的成员变量
-
能访问非静态的成员变量
-
能访问静态的成员方法
-
能访问非静态的成员方法
静态的成员方法:
-
能访问静态的成员变量
-
能访问静态的成员方法
用一句话来概括:静态成员方法只能访问静态成员;非静态成员方法 不但可以访问非静态也可以访问静态
4.2.3 static修饰的对象运行时的内存分配(掌握)
jvm方法区:
所有的方法区在逻辑上是属于堆的一部分,但是一些简单的实现可能不会选择区进行垃圾收集或者进行压缩。但是对于 HopSpot jvm而言,方法区还有一个别名 non-heap(非堆)。目的就在于和堆分开。
方法区可以看做是一块独立于java堆的内存空间
方法区主要存放的是Class(类信息),而堆中主要存放的是实例化的对象
HopSpot中方法区的演变
-
jdk7及以前 习惯把方法区称为永久代
-
jdk8 以后 使用元空间取代了永久代
jdk8以后 永久代不存在了,存储的类信息,编译后的代码数据都应移动到了元空间,元空间并没有处于堆内存,而是直接占用的本地内存。
元空间的本质和永久代是类似,都是对jvm规范中方法区的实现,元空间与永久代最大区别在于:元空间不在虚拟机设置的内存中,而是使用本地内存。永久代,元空间二者并不仅仅是名字变了,内部结构也调整了。
方法区存储的信息:类型信息 常量 静态变量以及编译后的代码数据等
类型信息:包名 类名 父类等
方法信息;方法名称 方法的返回值类型 方法的形参。方法的修饰符
non-final的类变量(static)
静态变量和类关联在一起的,随着类的加载而加载,他们成了类数据在逻辑上的一部分,类变量被类的所有实例对象共享,存在于方法区,即使没有实例对象,你也可以访问他。
5 单例设计模式
设计模式是在大量的时间中总结和理论化之后优选的代码结构 编程风格 以及解决问题的思考方式。
所谓的单例设计模式,就是采取一定的方法保证在整个系统运行中,对某一个类只能存在一个对象实例,并且该类只提供一个获取该类实例的方法。
单例设计模式的--饿汉式
public class Singleton { //1 私有化构造方法 private Singleton(){ } // 2 创建本类的一个静态对象 private static Singleton singleton = new Singleton(); //3 获取该类实例对象的方法 public static Singleton getInstance(){ return singleton; } }
单例设计模式的--懒汉式
public class Singleton { //1 私有化构造方法 private Singleton(){ } // 2 创建本类的一个静态对象 private static Singleton singleton ; //3 获取该类实例对象的方法 public static Singleton getInstance(){ if(singleton == null){ singleton = new Singleton(); } return singleton; } }
单例模式的优点:
由于单例模式只生成一个实例,减少了系统的开销,当一个对象的产生需要较多的资源时,比如读取配置文件,产生其他的依赖对象时,则可以通过在应用启动的时候直接产生一个单例对象,然后让其永驻内存的方式来解决
-
6.多态
6.1多态的概述
什么是多态?
同一个对象,在不同的时刻表现出来的不同形态。
我们可以说 猫是猫 : 猫 cat = new 猫();
也可以说猫是动物: 动物 animal = new 猫();
这里的猫在不同的时刻表现出不同的形态 称为多态
多态的前提条件:
1 要有继承关系(实现关系)
2 要有方法的重写
3 要有父类的引用指向子类对象。
多态要点:
1 多态是方法的多态,不是属性的多态(多态和属性无关)
2 多态的存在要有三个必要条件
-
要有继承关系(实现关系)
-
要有方法的重写
-
要有父类的引用指向子类对象。
3 父类的引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
具体来讲: 多态指的是同一个方法调用,由于对象不同可能会有不同的行为。
6.2 多态中的成员的访问特点
public class Animal {
public int age = 3;
public void eat(){
System.out.println("动物进食.....");
}
}
public class Cat extends Animal{
public int age = 2;
public int weight = 10;
@Override
public void eat(){
System.out.println("猫吃鱼...");
}
public void palyGame(){
System.out.println("猫抓老鼠玩....");
}
}
public class Dog extends Animal{
public int age = 4;
public String name = "旺财";
@Override
public void eat(){
System.out.println("狗吃骨头....");
}
public void work(){
System.out.println("狗看家....");
}
}
测试类
public class AnimalTest {
public static void main(String[] args) {
// 父类引用指向子类对象
Animal a1 = new Cat();
a1.eat();// 猫吃鱼
//a1.palyGame();//访问不到
System.out.println(a1.age);//3
Animal a2 = new Dog();
a2.eat();//狗吃骨头
System.out.println(a2.age);//3
}
}
如果在编译时和运行时类型不一致,就出现了对象的多态性。
多态情况下成员方法,看左边: 看的是父类的引用(父类中不具有子类特有的方法)
看右边 看的是子类的对象(实际运行时的子类重写父类的方法)
成员变量:不具备多态性,只要看引用变量声明的类型即可。
总结:
成员方法:编译看左边 运行看右边
成员变量:编译看左边 运行看左边
6.3 多态的好处和弊端
好处
提高了代码的扩展性。定义方法的时候,使用的是父类型作为参数,在使用是的时候,可以使用具体的子类作为真是的操作对象
弊端:不能访问子类特有的成员。
public class Person {
public void seedAnimal(Animal animal){
animal.eat();
}
}
public static void main(String[] args) {
Person person = new Person();
person.seedAnimal(new Cat());
person.seedAnimal(new Dog());
}
6.4 虚拟方法调用
Animal a = new Animal();
a.eat();//动物进食
// 父类引用指向子类对象
Animal a1 = new Cat();
a1.eat();// 猫吃鱼
//a1.palyGame();//访问不到
System.out.println(a1.age);//3
Animal a2 = new Dog();
a2.eat();//狗吃骨头
System.out.println(a2.age);//3
子类中定义了与父类同名同参数的方法,在多态的情况下,将此事父类的方法称为虚拟方法。父类根据赋给他的不同的子类对象,动态调用属于子类的该方法,这样的方法 的调用在编译器是无法确定的。
Animal a1 = new Cat();
a1.eat();// 猫吃鱼
编译时类型和运行时类型
编译时 a1 是Animal类型,而方法调用时在运行时确定的,所以表用的是Cat类的eat方法。这种称为动态绑定。
6.5 重写和重载的区别
重载:是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数列表,对同名方法的名称做修饰。对于编译器而言,这些方法变成了不同的方法。他们的调用地址在编译期就绑定了。java重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法,所以,对于重载而言,在方法调用之前,编译器就已经确定了要调用的方法,这种称为早绑定或静态绑定
而对于多态,只有等到方法调用时,执行器才会确定所要调用的具体的方法,这种称为晚绑定或动态绑定。
重载:可以使本类方法的重载,子类也可以重载父类的方法。重载的要求是方法名称相同,参数列表不同(个数不同,类型不同,顺序不同)
重写:一定是子类对父类的重写,重写要求方法的声明形式必须完全一致。