1、java语言特性
简单性、面向对象、可移植性(一次编译,到处运行)、健壮性(自动垃圾回收机制,GC)、多线程。
2、java的加载与执行
编译阶段:.java源文件---》.class字节码文件
加载与运行阶段:类装载器负责将.class装载到jvm中。jvm负责将class文件解释成二进制数据。
3、public class和class的区别
1、一个.java源文件中可以定义多个class,并且一个class会生成一个.class文件。
2、一个.java源文件中可以没有public的class,public的class必须和文件名保持一直。
4、标识符
java文件中可以自己命名的地方,统一称作标识符。
1、由数字、字母、下划线和美元符号构成。
2、不能以数字开头。
3、区分大小写
4、理论上没有长度限制
5、变量的作用域
出了大括号就不认识了。
变量根据出现的位置可以分为两种:局部变量和成员变量。
6、八种数据类型
关于基本数据类型转换规则:
1、8中基本数据类型除了boolean类型之外都可以相互转换
2、小容量向大容量转换叫做自动类型转换。
byte<short<int<long<float<double<char
3、byte,short和char做混合运算的时候,都会各自先转换成int在做运算。
4、大容量向小容量转换是属于强制类型转换。
5、如果整数没有超过byte,short,char的取值范围,可以直接将这个整数赋值给byte,short,char
6、多种数据类型做混合运算,先转换成容量最大的那种,再做运算。
7、什么是方法
1、方法就是一段代码片段,这个片段可以完成特定的功能,并且可以重复利用。
2、语法:【方法的修饰符列表】 方法的返回类型 方法名(参数列表)
3、return语句一旦执行,则方法结束。
4、什么时候会发生方法的重载?
发生在同一个类中、方法名相同、参数列表不同(类型,个数,顺序)
和方法的返回值类型无关、和方法的修饰符列表无关。
System.out是Sun提供的printStream类型,println是printStream类型的方法,该方法已经构成了重载。
5、方法在调用的时候,才会给该方法在内存中分配空间,如果这个方法只是定义没有调用,则不会在内存中分配空间。
6、方法在调用的时候,在“栈”中分配空间(JVM内存中有一块内存是栈内存)。
7、方法调用就是压栈,方法结束其实就是弹栈。
8、对象
1、所有new出来的东西都会在堆中进行存储。
2、Student student = new Student(); //student其实是一个引用,并不是一个对象。引用的是一个内存地址,指向堆中的对象。
3、程序员无法对堆中数据直接操作,只能通过内存地址间接操作。
4、成员变量在堆中的对象中存储,如果没有主动赋值,系统则默认赋值。局部变量在栈帧中存储。
5、成员变量只属于当前的对象(只属于对象,不属于类),只有通过对象才可以访问成员变量。
9、构造函数
1、Student student = new Student(); //new后面跟的就是构造器,构造方法。
2、如果提供一个有参的构造方法,系统则不会提供无参的构造方法。如果一个类已经手动提供了一个构造方法,那么系统不会再提供构造方法。
3、成员变量在构造方法调用时赋值
10、内存分析
1、方法区中存储的只是.class文件的代码、静态变量、常量等。
2、深入理解jvm,重点看第五章。
3、对象如果不存在,访问对象的变量或者方法,则出现空指针异常。
11、参数的传递问题
第一个例子为什么没有变?
因为传递的是引用数据类型,为内存地址。指的是堆中的对象。
12、this关键字
1、this是什么
this是一个引用类型,保存了内存地址,在堆中的每一个java对象中都有this。this保存内存地址指向自身。
2、this能用在什么地方
可以用在成员方法中,在成员方法中,this代表当前对象,谁去调用这个成员方法,this就代表谁。
可以用在构造方法中,通过一个构造方法调用另外一个构造方法。必须出现在构造方法第一行。
3、this可以用来区分成员变量和局部变量
4、this不能用在静态方法中
静态方法的执行根本不需要java对象的存在,直接使用类名. 的方式访问。而this代表的是当前对象。所以静态方法中根本没有this。
13 static关键字
1、static修饰的变量叫做静态变量、修饰的方法叫做静态方法、还可以定义静态语句块。
2、静态语句块在类加载的阶段就会执行里面的代码,并且只执行一次,并且是自上而下的顺序执行。
public class test{
//静态语句块
static{
System.out.println("1");
}
public static void main(String[] args){
System.out.println("2");
}
}
//执行结果
1
2
3、实例语句块
在每次构造方法调用的时候会执行。在每次构造方法调用之前执行一次。
public class test{
{
System.out.println("1");
}
public static void main(String[] args){
new test();
}
}
//执行结果
1
4、即使用引用.静态方法(); 底层也不会使用这个引用对象。因为静态方法的执行根本不需要对象。
5、静态变量存储在方法区,是类级别的,使用“类名.变量”的方式来访问。如果这个属性所有的对象都有,并且这个属性的值是相同的,则该属性声明成静态。在类加载阶段赋值,并且只赋值一次。
14、单例模式初步
1、设计模式:是可以重复利用的解决方案。从结构上分为三类:创建型、结构型、行为型。
2、对象实例创建完成之后,会放到堆中,如果堆中的实例太多,会存在特别多的垃圾。使用单例模式之后,只会创建一个实例,显著减少对象实例的个数,同时也会提高性能。
3、实现单例模式
public class Singleton{
//静态变量
private static Singleton s;
//构造方法私有化
private Singleton(){}
//对外提供一个公开获取实例的方法
public static Singleton getInstance(){
if(s == null){
s = new Singleton();
}
return s;
}
}
3、三要素:构造方法私有化、对外提供一个公开的静态的获取当前类型对象的方法、提供一个当前类型的静态变量。
4、单例模式分为两种:饿汉式单例和懒汉式单例
饿汉式单例:在类加载阶段就创建了对象
public class Singleton{
//饿汉式单例
private static Singleton s = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return s;
}
}
懒汉式单例:用到的时候才进行创建。
5、单例模式的缺点:
构造方法私有化,子类无法创建对象。
无法被继承。
15、继承
1、子类继承父类,会将父类中所有的数据全部继承,包括私有的也能继承过来,但是在子类中无法直接访问父类中的私有数据。但是可以间接访问(通过父类提供的set、get方法)。
2、构造方法无法被继承。
3、最基本的作用:代码的重用 最重要的作用:方法的重写。
4、重写的方法不能比被重写的方法拥有更低的访问权限、抛出更宽泛的异常。
5、私有的方法不能被重写,构造方法不能被重写。
6、多态:父类型引用指向子类型对象。
16、super、
1、super不是引用类型,super中存储的不是内存地址。super指向的不是父类型对象。代表的是当前子类对象中的父类型特征。
2、子类和父类中都有某个数据。例如都有name这个属性,如果要在子类中访问父类中的name属性,需要使用super
3、super可以用在成员方法中,super可以用在构造方法中。super不代表引用,所以不能用在静态方法中。
4、super就是this的一部分。this和super一样,都不能用在静态上下文中。
5、一个构造方法第一行如果没有this();或者super(); 系统会默认调用super();
6、对super的调用必须是构造函数的第一个语句。
7、super()和this()不能共存。
8、通过子类的构造方法去调用父类的构造方法,所用是:给当前子类对象中的父类特征赋值。
9、super()调用了父类的构造方法,但是不会创建父类对象。
10、构造方法执行,不一定构造对象。
17、final关键字
1、final修饰的类无法被继承。final修饰的方法无法被覆盖。final修饰的局部变量,一旦赋值,不可再改变。final修饰的成员变量,必须显示的初始化。
2、final修饰的成员变量一般和static连用。放在方法区。
3、public static final int PI = 3.14; 中PI就叫做常量。java规范中要求,所有的常量大写。
4、final修饰的引用类型,该引用不可再重新指向其他的java对象,但是final修饰的引用,该引用指向的对象的属性是可以修改的。
18、抽象类
1、class关键字前加 abstract;
2、抽象类无法被实例化。
3、虽然无法实例化,但是有构造方法,该构造方法给子类创建对象用的。
4、抽象类中可以定义抽象方法(只有方法头,没有方法体,使用abstract修饰)。
5、一个非抽象类继承抽象类,必须将抽象类中的抽象方法实现、覆盖、重写。
19、接口
1、接口中只能出现:常量、抽象方法。
2、接口其实是一个特殊的抽象类,特殊在接口是完全抽象的。
3、接口中没有构造方法,无法被实例化。
4、接口和接口之间可以多继承。
5、一个类可以实现多个接口
6、一个非抽象的类实现接口,需要将接口中的所有方法实现\重写\覆盖。
作用:
面向接口调用方法,不需要关心接口是怎么实现的。
public class Test{
public static void main(String[] args){
//面向接口去调用
//CustomerServeice 为接口 CustomerServiceImp为接口的实现类
CustomerService cs = new CustomerServiceImp(); //多态
//调用
cs.logout();
}
}
1、可以使用项目分层,所有层都面向接口开发,开发效率提高。
2、可插拔。使代码和代码之间的耦合度降低。就像内存条和主板的关系,变得可插拔。
抽象类与接口优先选择接口(保留了类的继承)。
20、Object类
1、是所有类的根基类。
2、如果类在声明中未使用extends关键字指明其基类,则默认基类为Object类。
3、设计toString的目的:返回java对象的字符串表示形式。就是要被重写的。
4、print方法后面括号中如果是一个引用类型,会默认调用引用类型的tostring方法。
5、equals方法:比较的是内存地址,在现实的业务逻辑中,不应该比较地址,应该比较内容,所以需要重写。
6、String类已经重写的Object类中的equals()方法;
public boolean equals(Object obj){
return this == obj;
}
// ==两边如果是引用类型,则比较的是内存地址。
7、比较两个字符串是否一致,不能使用“==” ,只能调用String的equals方法。https://www.htzyw.com/
21、finalize方法
1、垃圾回收器:也叫GC。
2、垃圾回收器在回收对象之前,会自动调用对象的finalize方法。不需要程序员去调用。
3、java对象如果没有更多的引用指向它,则该java对象成为垃圾数据,等待GC的回收。
4、源代码中并没有实现,所以明摆着是让我们重写的。
5、程序员只能建议GC去回收System.gc();
22、包和import
包
1、为了解决类的命名冲突问题,在类名前加命名空间(包机制)。
2、使用pakage语句定义包。分为单包和复包。
3、pakage语句只能在第一行。定义的格式通常采用公司域名倒叙方式。 com.leodon.car.system.表示leodon公司car项目。system是项目中的一个模块。
4、完整的类名是带有包名的。
5、import语句可以引入其他类,只能出现在package语句之下,class定义的语句之上。
访问控制权限
1、private:类内部可以访问
2、default:类内部可以访问、同一个包里可以访问。
3、protected:类内部可以访问、同一个包里可以访问、子类可以访问
4、public:类内部可以访问、同一个包里可以访问、子类可以访问、任何地方都可以访问。
以上对类的修饰只有:public和default,内部类除外。
23、inner class内部类
静态内部类
1、可以等同看作静态变量。
2、内部类重要作用:可以访问外部类中的数据。
3、静态内部类可以直接访问外部类的静态数据,无法直接访问成员。
public class outclass{
//静态变量
static String s = "A";
//成员变量
private String s2 = "B";
//静态方法
private static void m1(){
sout("m1");
}
//成员方法
private void m2(){
sout("m2");
}
//静态内部类,可以用访问控制权限的修饰符修饰
//可以直接访问外部类的静态数据。
//public protected private default
static class innerclass{
//静态方法
public static void m3(){
sout(s);
sout(s2); //error
m1(); //可以
m2(); //error
}
//成员方法
public void m4(){
sout(s);
sout(s2); //error
m1(); //可以
m2(); //error
}
}
}
成员内部类
1、可以等同看作成员变量
2、成员内部类中不能有静态声明。
3、成员内部类可以访问外部类所有的数据。
局部内部类
1、局部内部类可以等同看作局部变量。
2、局部变量没有修饰符,所以局部内不能不能用修饰符修饰。
3、内部类中不能有静态声明。
4、重点:局部内部类在访问局部变量的时候,局部变量必须使用final修饰。
5、不能在main方法中创建对象,只能在方法中创建对象。
匿名内部类
1、指的是类没有名字,
public class Test{
//静态方法
public static void t(CustomerServiece cs){
cs.logout();
}
public static void main(String[] args){
//调用t方法
t(new CustomerSerciece(){
public void logout(){
sout("exit");
}
});
}
}
interface CustomerSrerviece{
void logout();
}
2、优点:少定义一个类。缺点:无法重复使用。
24 类之间的关系
泛化关系
类和类之间的继承、接口和接口之间的继承。
实现关系
类实现了接口,它们之间属于实现关系。
关联关系
类与类之间的连接,一个类可以知道另一个类的属性和方法。在java语言中通常使用成员变量来体现。
public class me{
String name;
Friend f; //me和Friend就是关联关系
}
public class Friend{
}
聚合关系
是关联关系的一种,是较强的关联关系,是整体和部分的关系。例如汽车和轮胎,与关联关系不同,关联关系表示类处在一个层次上,而聚合关系的类并不是处在一个层次上。
例如:教室和学生。整体不依赖部分,部分也不依赖整体。
合成关系
合成关系和聚合关系是相似的。
区别的地方在于:整体和部分是紧密相连的,整体的生命周期决定部分的生命周期。
依赖关系
概念:
依赖关系描述了一种,“类与类之间” 一种 “使用与被使用” 的关系
依赖关系在Java中的具体代码表现形式为B为A的构造器或方法中的局部变量、方法或构造器的参数、方法的返回值,或者A调用B的静态方法
简单来说,就是 A 类中, 出现了 B 类
例子:
汽车依赖汽油
// 汽车
class Car {
// 跑
public void run(Petrol petrol) {
System.out.println("使用:" + petrol.type + ", 汽车跑了起来~");
}
}
// 汽油
class Petrol {
// 构造
public Petrol(String type) {
this.type = type;
}
// 汽油型号
public String type;
}
public class YiLai {
public static void main(String[] args) {
// 使用场景
Car car = new Car();
car.run(new Petrol("93号汽油"));
}
}
run()
方法传递的参数, 汽车依赖了汽油。
汽车对汽油发生了依赖关系,那么就是汽车对汽油产生了耦合