三条主线:
1.java类及类的成员:属性,方法,构造器,代码块,内部类
2.面向对象的三大特征:封装性,继承性,多态性
3.其它关键字
面向对象和面向过程对比:
面向过程:强调功能行为,以函数为最小单位,考虑怎么做
面向对象:强调具备功能的对象,以类/对象为最小单位,考虑谁来做
类和对象:
类是对一类事物的抽象,概念上的定义,也就是相当于一个模板
对象:是存在的事物
面向对象的重点是设计类—>设计类就是设计类的成员
属性=成员变量=field=域、字段
方法=成员方法=函数=methed
对象的内存分析:
-
堆:此内存区域的唯一目的就是存放对象实例,几乎所有对象实例都在这里分配内存。
java虚拟机规范中描述:所有对象实例以及数组都在堆上分配
-
栈:是指虚拟机栈,用于存储局部变量,局部变量存放了编译期可知长度的各种基本数据类型(boolean、byte......double)方法执行完,自动释放。
-
方法区:用于存储已被虚拟机加载的;类信息、常量、静态变量
属性与局部变量的对比
-
相同之处:①定义变量格式相同 变量名=变量值 ②先声明,后使用③变量都有其对应的作用域
-
不同之处:①声明位置不同,属性直接定义在类中,局部变量定义在方法内,形参,代码块中
②关于权限修饰符不同 :属性在声明属性时,指明其权限修饰,使用其权限修饰符,而局部变量 不可以。
3.初始化值情况:属性:类的属性,根据其类型,都有默认初始化值
局部变量:设有默认初始化值。意味着我们调用局部变量之前,一定要显示赋值
方法:
概述:描述类应具有的功能。
方法的声明:权限修饰符 返回值类型 方法名(形参类型){
方法体}
权限修饰符:private,public,缺省,protected
返回值类型:有返回值 vs 没有返回值
若有返回值,必须在方法声明时,指定返回值类型。同时方法中,需使用return返回指定变量或常量
方法名:属于标识符,遵循标识符的规则和规范,"见名知意"
形参列表:方法可声明0个,1个,多个形参
构造器(constractor):
一:构造器作用:1.创建对象:new+构造器
2.初始化属性
二:说明:1.如果没有显式的定义一个构造器,则系统默认提供一个空构造器
2.定义构造器格式:权限修饰符 类名(形参列表)
3.一个类中定义多个构造器,彼此构成重载
4.一旦我们显式地定义了构造器后,系统则不会再提供空参构造
return关键字:
使用范围:方法体中。
作用:①结束方法②针对有返回值的方法,使用"return 数据"
注意:return后不可声明执行语句
方法使用:可以调用当前类中的方法和属性 特例:方法A中调用方法A 递归方法
方法中不可定义方法
理解万事万物皆对象:
1.在java语言范畴,我们将功能,结构封装在类中,通过类的实例化,来调用具体的功能和结构。
2.涉及java语言与前端HTML,后端数据库交互时,前后端结构在java层面交互时,都体现为类,对象。
匿名对象的使用:
1.即只new对象不给其命名。
2.特征:匿名对象能调用一次
方法的重载:
1.定义:在一个类中,允许存在多个同名的方法
2."两同一不同":同一个类,相同的方法名
参数列表不同,参数个数不同,参数类型不同
3.判断是否重载:跟方法的权限修饰符,返回值类型,形参变量名,方法体都无关
4.在通过对象调用方法时,如何确定一个指定的方法①方法名②参数列表
方法参数的值传递机制:
如果变量为基本数据类型,此时赋值的是变量所保存的数据值
如果变量为引用类型,此时赋值的是变量保存的地址值
面向对象的特征之一:
封装:程序设计追求:"高内聚,低耦合"
-
高内聚:类的内部数据操作自己完成,不允许外部干涉
-
低耦合:仅对外部暴露少量方法用于使用
隐藏对象内部复杂性,只对外公开简单的接口,便于外部调用,从而提高系统的可拓展性,可维护性
问题引入:
创建一个类后,可通过"对象.属性"的方法进行赋值,这里的赋值要受属性的数据类型和存储范围制约。除此之外,无其他制约条件。在实际问题中,我们往往需要给属性赋值加入额外限制条件。这条件不能在属性声明时体现,只能通过方法进行制约,则需要将属性声明私有化(private)
封装的体现:将类的属性xxx私有化(private),同时,提供公共的方法来获取(get)和设置(set)
拓展:①私有化属性②不对外暴露私有方法③单例模式
封装的体现需要通过限制修饰符来配合:
java中的四种限制修饰符:private,缺省,protected,public
修饰符 | 类内部 | 同一包内 | 不同包的子类 | 其他包 |
---|---|---|---|---|
private | yes | |||
(缺省) | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
对class的权限修饰只可以用public和default(缺省)
public类可以在任意地方被访问
default类只可以在同一个包内部的类使用
4种权限修饰可以用来修饰类及类内部结构,属性,方法,构造器,内部类
修饰类的话 public或缺省
类成员三:构造器
一:作用
:1.创建对象:new+构造器
2.初始化属性
二:说明:1.如果没有显式地定义一个构造器,则系统默认提供一个构造器
2.定义构造器格式:权限修饰符 类名(形参列表)
3.一个类中定义多个构造器,彼此构成重载
40一旦我们显式地定义了类的构造器后,系统不再提供空参构造
JavaBean:
-
JavaBean是一种java语言写成的可重用组件
-
所谓JavaBean。是指符合如下标准的Java类
-
类是公共类
-
有一个无参的公共构造器
-
有属性,且有对应的get,set方法
-
用户可以使用javabean将功能,处理,值,数据库访问和任何可以用Java代码创造的对象进行包装,并且其他开发者可以通过内部的JSP页面、servlet、其他javapean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用担心任何改变
-
继承性:
一:继承性的好处
-
减少代码冗余,提高代码的复用性
-
便于功能的拓展
-
为之后的多态的使用,提供前提
二:继承格式:class A extends B{}
A 子类 派生类 subclass
B 父类 超类 基类 superclass
2.1体现:一旦子类A继承父类B后,子类A获取了父类B中的声明的所有属性,方法
特别:父类声明的为private的属性和方法,子类继承父类后,仍认为获取了父类中私有结构,只是因为封装性的影响,使得子类不能直接调用父类的结构而已。
2.2子类继承父类之后,还可以声明自己特有的方法或属性,实现功能的拓展
三、java中关于继承性的一些规定
java只支持单继承和多层继承,不允许多继承
即1.一个类可以被多个子类继承
2.一个类只可以有一个父类
3.子父类关系是相对的
4.子类继承父类后,就获取了直接父类(子类直接继承)以及所有间接父类(间接继承)声明的属性和方法
四:1.如我们没有显式地声明一个类的父类的话,则此类继承java.lang。Object类
2.所有java类(除java.lang.Object类之外)都直接或间接继承java.lang.Object类
3.意味着,所有java类具有java.lang.Object类声明的功能
方法的重写
概述:1.子类继承父类之后,可以对父类中同名的方法,进行覆盖操作
2.应用:重写后,当创建子类对象后,通过子类调用子类的同名同参数方法,实现的是子类重写父类的方法
3.重写的规定:
方法的声明:权限修饰符 返回值类型 方法名(形参列表){ 方法体}
约定俗称:子类中的叫重写的方法,父类中叫被重写的方法
①子类重写的方法的方法名和形参列表与父类中被重写的方法必须相同
②子类重写的方法的权限修饰符不可以小与被重写的方法的权限修饰符
》特殊情况:子类不能重写父类中声明为private的方法
③返回值类型
》父类被重写的方法的返回值类型为void,则子类重写的方法的返回值类型只可以为void类型
》父类被重写方法的返回值类型为A类型,则子类重写的方法的返回值类型只能为A类或者A类的子类
④子类重写的方法抛出异常类型不大于父类被重写方法抛出异常类型
子类和父类同名参数的方法要么都声明为非static的(考虑重写),要么都声明为static(不考虑重写)
多态性:可以理解成一个事物的多种形态。
对象的多态:父类的引用指向子类的对象(或子类的对象赋给子类的引用)
多态的使用,当调用子类同名同参数方法时,实际执行的是子类重写父类的方法--虚拟调用
虚拟方法调用:
有了对象的多态性之后,我们在编译期,只能调用父类中声明的方法,但在运行期间实际执行的是子类重写的方法。
总结:编译看左边,运行看右边
多态的使用前提:①类的继承②子类重写父类方法
对象的多态性,只适用于方法,不适用于属性。
虚拟方法调用的再理解:
前提:多态情况下
子类中定义了与父类同名同参数的重写方法,在多态情况下,将此父类的方法称为虚拟方法,父类据赋值给它的不同子类对象,动态调用子类的该方法,选择的方法调用在编译器时无法确定的
重载和重写
1.二者定义细节
2.从编译期和运行角度看
重载:是指允许在多个同名方法,而这些方法参数不同。编译器根据方法的不同参数列表,对同名方法的名称作修饰。对于编译器而言,这些同名方法成了不同方法,他们调用地址在编译期便绑定了,java重载时可以包括父类和子类,即子类可以重载父类的同名不同参数的方法。
所以,对重载而言,在方法调用之前,编译器就已经确定了要调用的方法,这称为"早绑定"或"静态绑定"。
而对于多态,只有等待方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为"晚绑定"或"动态绑定"
复习:
应用数据类型==,比较的是两个引用数据类型的地址值是否相同
引用数据类型:引用数据类型较多,大致包括:类,接口类型,数组类型,枚举类型,注解类型,字符串类型。
简单来说:所有非基本数据类型都是引用类型。
基本数据类型与引用类型的区别:
存储位置:基本数据类型:在方法中定义的非全局类型变量的具体内容存储在栈中
引用数据类型:只要是引用数据类型,其具体内容都存在堆中,而栈中存放具体内容地址
Object类的使用
1.object类是所有java类的根父类
2.如果在类声明中未使用extends关键字指明其父类,默认父类为java.lang.Object类
3.Object类中的功能(属性、方法)具有通用性。
4.Object类中之声明了一个空参的构造器。
方法:①clone() 复制一个对象
②getclass() 获取当前对象的类
③hashcode() 返回当前对象哈希值
面试题:==和equals()的区别
一:回顾==的使用
一.2:运算符:1.可以使用在基本数据类型便量和引用数据类型变量中。
2.如果比较的是基本数据类型:比较的两个变量保存数据是否相同(不一定类型相同),如过比较引用数据类型,比较两个变量的地址值是否相同,即两个引用是否指向同一个对象。
二:equals()的使用
1.是一个方放。而非运算符。
2.只适用于引用数据类型
3.Object类中对于equals()的定义:
public boolean equals(Object obj){ return (this=obj); }
说明Object类中定义的equals()和==的作用相同,比较两个对象的地址值是否指向同一个对象实体。
4.像String、Date、File、包装类等都重写了Object类中的equals()方法。重写后,比较的不是两个引用地址是否相同,而是比较两个对象内容是否相同。
5.自定义如何使用equals(),实现比较两个对象"实体内容"相同的目的。
面试题:==和equals()的区别
1.==即可比较基本类型也可比较引用类型,对于基本数据类型比较的是值,对于引用数据类型就是比较内存地址。
2.equals()的话,它是属于java.lang.Object类里面的方法,如果该方法未被重写默认是==,我们可看到String等类的equals()是被重写过的,二且String类在日常开发中,用的比较大,久而久之,形成了equlas()比较值的错误观点。
3.具体看自定义类中有无重写Object的equals方法来判断。
4.通常情况下,重写equals()方法,会比较类中的相应属性是否都相等。
toString()方法:
1.当我们输出一个对象引用时,实际上调用当前对象toString()
2.Object类中的toString()的定义:
public String toString(){ return getclass().getName()+"@"+Integer.toHexString(hashCode); }
3.像String、Date、包装类等都重写了toString()方法,使得调用对象的toString()时,返回"实体内容"。
包装类(Wrapper)的使用
-
针对八种基本数据类型定义相应的引用类型—包装类(封装类)
-
有了类的特点,就可以调用类中的方法,java才是真正地面向对象。
基本数据类型、包装类的转换:
1.java提供8中基本数据类型的包装类,使得基本数据类型的变量有类的特征。
2.掌握基本数据类型、包装类、String三者之间的转换关系
基本数据类型-->包装类,调用包装类的构造器
应用:方法形参为类类型,将基本数据类型转换为类类型即可使用
例:
//① int sum1=1; Integer in1=new Integer(num1); System.out.println(in1.toString); //②也可 Integer in2=new Integer("123abc"); System.out.println(in2.toString); //错误形式 //Integer in3=new Integer("123abc"); //System.out.println(in3.toString()); 报异常 Float f1=new Float(12.3); Float f2=new Float("12.3"); System.out.println(f1); System.out.println(f2); //特例 class Order{ boolean isMale; boolean isFamale; } public void Text(){ public void text(){ Order order =new Order(); System.out.println(order.isMale);//false System.out.println(orde.isFamale);//true //基本数据类型转化为包装类后,默认值改变 } }
包装类—>基本数据类型:调用包装类xxx的xxxValue()方法
应用:包装类不可做加减乘除运算,转换为基本数据类型
例
public void text(){ Integer in1=new Integer(12); int i1=in1.inValue(); System.out.println(i1+1); Float f1=new Float(12.3); Float f2=f1.floatValue(); }
自动拆箱与自动装箱:
jdk5.0新属性:自动装箱和自动装箱
例:
public void text(){ //自动装箱 基本数据类型——>包装类 int num2=10; Integer in1=true; Boolean b2=b1; //自动拆箱 包装类——>基本数据类型 System.out.println(in1.toString()); int num1=in1 }
基本数据类型包装类与String的相互转换:
基本数据类型包装类——>String类型
public void test(){ int num=10; //方法一:连接运算 String str1=num1+""; //方法二 Float f1=12.3f; String str=String.valueOf(f1);//"12.3" Double d1=new Double("12.4"); String str3=String.valueOf(d1); System.out.println(str2);//12.3 System.out.println(str3);//12.4 }
String类型——>基本数据类型包装类
public void text(){ String str1="123"; //错误情况 //int num1=(int)str; 即不可强转 //Integer in1=(Integer)str1; int num2=Integer.parseInt(num1+1); String str2="true"; Boolean b1=Boolean.parseBoolean(str2); System.out.prinln() }
接口:
-
本质上讲,接口是一种特殊的抽象类,这种抽象类中包含抽象方法。
可以将接口看做是一个纯正的抽象类,作为设计层面使用的,用来定义功能(方法),具体的实现交给具体的类。
接口更加抽象,在jdk8之后添加静态方法和默认方法
implents修饰的为接口,实现时使用关键字implements
抽象类和接口的共同点:
1.都是一种抽象2.都不可被实例化3.都是用来被其他类继承
区别:
抽象类:
-
抽象类可定义成员变量
-
抽象类可以有构造方法
-
抽象类可以定义非抽象的成员方法
(抽象类中包含抽象方法,不能创建对象,其他功能与正常类没有区别)
接口:
-
接口只能定义常量,抽象方法,静态方法,默认方法
-
接口中不能有构造方法
-
接口可继承多个接口