后端工程师入门java的学习记录
初步更新可能比较散乱,日后有时间再慢慢完善
一、面向对象在和对象打交道,对立面向过程(强调动作)。
常见的思想,符合人们的思考习惯
遇到问题,先找他是否涉及哪个对象
描述现实中的东西,通常用类来实现(通常只关注属性和行为),通过NEW来产生该类事物的对象。
局部变量存在于栈内存的方法中(没有默认初始化值),成员变量存在于堆内存的对象中(有默认初始化值)。
类类型的变量要不指向对象,要不为空。
如果这个对象的属性或者方法只用一次,那么可以创建匿名对象。
二、特性-封装private 只能在本类中操作。(我自己)
protected 只能给我的子类用。(我儿子)
default 在同一个包中操作。(我邻居)
public 谁都可以用。
定义了类属性,这个属性往往是私有的,要通过public set或者public get来操作.(javabean的封装规范)
构造函数,创建对象时调用的函数。作用:可以给对象初始化属性。
一个类中如果出现多个构造函数,那么一定是重载形式的。
构造函数一旦定义过了,就不会找那个默认的构造函数了。
无法访问的语句-----不允许有废话出现。
This(这个对象的)关键字,为了区分局部变量和成员变量的名字。----所在函数 所属对象的引用。 简单:哪个对象调用了this所在的函数,this就是那个对象。
一个类中的所有成员,想要被调用,就必须用对象调用。This()可用于在构造函数中调用其他构造函数,必须定义在构造函数的第一句话,因为初始化动作要先执行。
只要在本类中,用到了本类的对象,通常都要用this
Static是一修饰符,用来修饰成员,共享的成员。
Static优先于对象存在,类的加载之后就存在了。可以用类名调用。
静态变量和成员变量的区别1.生命周期不同2.调用方式不同。
静态方法中不能找到非静态成员,不可以使用this关键字
Public static void main 1.public权限最大 2.static 虚拟机在调用时是不需要对象的 3.void 没有具体的返回值 void为空的时候,return可以省略
对象是万能的(即可以调用静态的,也可以调用非静态的)
何时用static修饰?对象的属性值都是相同的公有的;对象的方法需要访问非静态的属性时,那么也要修饰成非静态的。没访问对象特有的数据,最好用static修饰(没访问特有数据了,就别创建对象占堆内存了!)
Static{}静态代码块随着类的加载而执行,仅执行一次。用处:给类初始化,因为一些类是不需要创建对象的(里边都是静态的成员时)构造代码块—给对象初始化用的,有对象才执行。局部代码块—限定局部变量的生命周期。
类中一个非静态方法都没有,称为工具类。直接用类名调用方法不用创建对象了。并且可以强制不让其创建对象(把构造函数前加private)
单例
单例设计模式:对于多个程序使用一个配置信息时,该配置信息的对象应该唯一
保证对象唯一的方式:
1.不允许其他程序new对象--将构造方法私有化。
2.在本类中new一个对象
3.提供一个静态的public方法来获得这个对象
class Person //懒汉式
{
private Person(){};
private String name="fuheyi";
private int age=25;
private final static Person p = new Person();
public String getNA(){
return name+age+"";
}
public static Person rep(){
return p;
}
}
class Person //饿汉式,避免了多线程时带来的单例模式安全性问题
{
private Person(){};
private static Person p=null;
public static Person getInstance(){
//如果对象为空,才进入同步,否则就不判断同步锁了,浪费资源
if(p==null){
synchronized(Person.class){
//对象为空时才创建,不为空就不创建
if(p==null) {
p=new Person();
}
}
return p;
}
}
三、特性-继承
例如:学生和工人,都有年龄和姓名这些公有的属性,则可以让他们继承人这个类。学生是人-->is a
继承的好处:1.提高了代码的复用性。2.让类与类之间产生了关系3.给第三个特征多态提供了前提。
继承所解决的问题是共性抽取。
单继承:一个子类只能有一个直接父类。
要使用一个集成体系时,查看顶层类,并且熟悉其中的方法,创建最底层的子类,完成功能的使用。
什么时候定义继承?当类与类之间存在所属关系时(狼和狗都属犬科)
如果子类和父类的成员重名,this(本类对象的引用)代表子类,super(父类的空间)代表父类,用法很相似。
this关键字的应用:访问本类的成员变量、本类的成员方法、本类的构造方法中访问本类的另一个构造方法。
当子父类中有相同的成员函数,调用时会优先运行子类的成员函数,这个称为覆盖操作。子类函数覆盖父类函数时,权限必须大于或者等于父类权限,静态函数只能被静态函数覆盖。
什么时候使用覆盖操作?当一个类要做子类的功能扩展时,要保留父类的方法名,但方法体内容要更新,就是用覆盖来完成。@override注解可以标识方法是一个覆盖方法并验证是否有效
子类覆盖方法的返回值只可以是父类返回值类型的子类。
子类覆盖方法的访问范围要大于等于父类的,例如父类方法是protect,那么子类就不能是private。
子类的实例化过程,所有的子类构造函数都会默认调用父类的空参数构造函数。super();
为什么子类在实例化时,会访问父类的构造函数呢?你用父类的属性时,要知道人家是怎么初始化的,所以要先调用一下父类的构造函数。如果父类没有空参数的构造函数,则必须在子类构造函数中•用super(参数)来明确调用父类的哪个构造函数。
super关键字的应用:子类调用父类的方法、属性、和构造函数时使用。
Java中创建的所有的类,都是Object的子类。创建对象的步骤:
1.JVM加载,将类和父类加载进方法区,方法区就是共享区,class加进去就不退出去了。
2.在堆内存开辟空间分配地址,对像属性进行初始化。
3.调用子类构造函数,在子类构造函数第一行先调用父类super()进行初始化。
4.再对子类的构造代码块进行初始化,再对子类构造函数的属性进行显示初始化,再对子类构造函数进行特定初始化。
5.将对象堆内存地址赋值给引用变量。
Final修饰符,可以修饰类、方法、变量。修饰类之后不可以被继承;修饰方法之后不可以被覆盖;修饰的变量是一个常量;成员变量一旦被final修饰,通常都会加static静态。
Abstract 抽象,不具体的类和方法。能确定功能,但是不确定功能细节的方法就是abstract方法。抽象类的特点:1.方法只有声明,没有方法体时2.抽象类不能创建对象3.子类把所有抽象方法都覆盖后才能实例化。
抽象类细节:
1.抽象类有构造函数吗?有,用于给子类对象初始化。
2.抽象类里可以不定义抽象方法吗?可以,但是很少见,目的就是不让该类创建对象。
3.抽象Abstract与那些关键字不共存?private、final、static
4.抽象类和一般类的区别?都是用来描述事物的,都在内部定义了成员。不同在于抽象类描述实物是模糊的;一般类中不能定义abstract方法,抽象类中可以定义非abstract方法。
5.抽象类一定是父类吗?是的
接口就是公共的规范
Interface 当一个抽象类中所有方法都是抽象方法,则称为接口。
接口中常见的成员
1.抽象方法public abstract void fhy();
2.全局常量public static final String FHY=”付赫奕”;
3.接口中的成员,权限最大了,修饰符即使不写也会默认给你加上。public 与abstract
JAVA8的接口还包含了默认方法、静态方法;JAVA9还包含了私有方法。
默认方法:public default void fhy(){};//方法修饰符是默认的,并且有方法体。有什么用?可以解决接口升级的问题;我改了一个接口,这个接口要是有100个实现类呢?全都要实现一遍吗?有了默认方法之后就不用了。
静态方法:public static void fhy(){};这个有什么用?有一些内容跟对象没什么关系,并且可以共享。静态的就是跟对象没关系的,直接通过类来调用。
私有方法:当JAVA8中的默认方法和静态方法中有重复的部分,JAVA9就可以再抽取出来一个新的方法,但又不想给实现类使用,就要私有。只为了在接口内部使用的私有方法。
接口不能实例化,只能由实现了接口所有抽象方法的子类来实例化。Implements
Java不支持多继承,会增加不确定性,但可以用接口多实现。(多继承的方法有方法体导致运行结果不一样,而接口多实现则只有方法名,这样不会有不确定性了)
接口与接口之间,是继承关系extends。
接口好处:1.功能对外暴露。2.降低耦合性。2.支持功能扩展。
抽象类与接口:1.都是向上抽取来的。2.抽象类需要继承,接口需要实现和多实现。3.抽象类中可以继承抽象方法和非抽象方法,而接口必须定义抽象方法,并且必须由子类全部实现。4.继承是进入了父类体系,实现是附加了额外的功能。
接口的应用:由于前期定义了规则,所以可以使用后期生产的设备,因为设备是按照前期定义的规则来生产的
一个类实现了两个接口,但是两个接口的方法冲突,这时只需实现一次即可。JAVA9以上版本里如果有默认方法冲突了,则子类必须覆盖默认方法。如果继承了父类和接口时,默认方法冲突了,那么优先使用父类的方法,接口的优先级低
四、特性-多态一个父类的引用指向一个子类的对象,这个就是多态的体现(一个鼠标可以指向一个USB类型的类)简单说:就是一个对象对应着多个类型(猫属于猫类,也属于动物类)
父类 变量名=new 子类();----一个对象两种形态
多态的好处:提高了代码的扩展性。
多态的弊端:前期定义的父类引用,不能使用子类后期扩展的方法,只能使用覆盖的方法。
向上转型提高扩展性,向下转型为了使用子类特有的方法。
Animal cat=new Cat(); //自动把猫提升位动物,动物就不能再去玩老鼠了---向上转型
cat.eat();
Cat cat1=(cat)cat;//为了使用猫类中的特有方法-----向下转型(造型) 只有子类能转换成父类 (重点掌握)---如果父类转子类的话,会出现ClassCastException
cat.玩老鼠();
多态的前提:1.类之间必须有关系,继承或者实现。2.要有覆盖.3。覆盖只发生在函数上,跟属性没关系
//a instanceof Dog ----用于判断对象的类型,只能用于判断引用型变量。通常是在向下转型前做健壮性的判断。 static void dongwu1(Animal a){ a.eat(); if(a instanceof Cat){ Cat c=(Cat)a; c.wanLaoshu(); }else{ Dog d=(Dog)a; d.lookHome(); } }
fu f=new zi(); 编译和运行都主要依据左边的类型,编译运行都看左边的对象的属性(成员变量)。
f.show(); 父类中必须有show方法,编译看左边运行看右边。
静态函数的多态,是优先寻找的引用类型所属的类的函数(左边)。(对于静态函数,并不涉及多态性,用类调用就行了)
为什么要有内部类?? (人体内存在着心脏)在分析事物时,事物1中还存在一个事物2,并且还需要访问外部的事物1内容。所以将事物2定义成内部类。
1.内部类可以直接访问外部类的成员
2.外部类访问内部类,必须要创建内部类的对象
外部.内部 neibu=new 外部().new 内部();
内部类相当于成员,可以加四种修饰符。
内部类在局部方法里,什么都不用写,因为不涉及跨类的调用。
内部类是静态的,就相当于一个外部类;如果内部类成员也是静态的,就可以直接都用类调用了
内部类是非静态的,其中就不能有静态的成员。静态成员都是类加载时就完成的,而非静态内部类是在外部类创建对象之后才初始化。
想用谁的成员,就得拿谁的对象来调用。
内部类,在局部位置上(成员函数中),那么这个类不能被外部实例化,只能在成员方法内实例化,并且只能通过调用所属的成员方法来使用局部内部类。只能访问局部final 变量。因为局部变量周期短,内部类在堆里周期长,不加final就会访问不到。
匿名内部类,就是内部类的简写格式。
其实就是父类的匿名子类对象,通常继承一个类,就是覆盖父类的方法,再创建子类对象,现在是直接创建父类对象时直接覆盖了其中的方法。
格式
new 父类或接口名(){子类要覆盖父类的方法}
当函数参数是接口类型时,并且其中的方法不超过三个时。用此写法
class Fuzi {
public static void main(String args[]) {
show(new Animal() {
public void eat() {
System.out.println("haha");
}
});
}
public static void show(Animal a) {
a.eat();
}
}
interface Animal {
void eat();
}



