------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
面向对象
面向对象是一种常见的程序结构设计方法。面向对象是相对于面向过程而言,将与其相关的方法,数据放在一起,如冰箱的开关动作封装进冰箱类中,从人将冰箱打开变成命令冰箱打开,:人.开冰箱—>冰箱.开。这可以将许多复杂的问题简单化,将程序员从执行者变成了调用者。
面向过程与面向对象的区别:
面向过程:强调的是功能行为,一种过程,先干啥,再干啥;
面向对象:将功能封装到对象里,强调的是具备某功能的对象;
按照面向对象的思想,可以把任何的东西看做对象。(万物皆对象)
面向对象的特征
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
在面向对象的开发过程中就是不断的创建对象,使用对象,指挥对象做事情。设计过程其实就是在管理和维护对象之间的关系。
类与对象的关系
java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义,在定义类时其实就是在不断描述现实生活中事物。而对象则是该类事物实实在在存在的个体。
定义一个类:在现实生活中如何描述一样事物呢?不外乎描述属性和行为。在java中用class来描述事物也是如此,属性和行为,属性à对应类中的成员变量,行为à对应类中的成员函数。
成员变量和局部变量的区别:
成员变量:成员变量定义在类中,在整个类中都可以被访问。
成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
成员变量有默认初始化值。
局部变量:局部变量只定义在局部范围内,如:函数内,语句内等。
局部变量存在于栈内存中。
作用的范围结束,变量空间会自动释放。
局部变量没有默认初始化值。
构造函数
特点:
函数名与类名相同
不用定义返回值类型
不可以写return语句
作用:
给对象进行初始化。
多个构造方法是可以以重载的形式存在
封装
封装的两个含义:
1.把对象的状态和行为看成一个统一的整体,将二者存放在一个独立的模块中(类);
2."信息隐藏", 把不需要让外界知道的信息隐藏起来,尽可能隐藏对象功能实现细节,字段;
在程序中,通常把类中成员私有化(private),并且对外提供setXxx,getXxx方法让其对xxx进行访问。
*单利设计模式:一个类在内存中只存在一个对象:
示例:
package com.itheima;
public class SingleDemo {
public static void main(String[] args) {
Single1 s1 = Single1.getInstance();
Single1 s2 = Single1.getInstance();
System.out.println(s1==s2);
//true,因为是同一个对象。
Single2 s3 = Single2.getInstance();
Single2 s4 = Single2.getInstance();
System.out.println(s3==s4);
//true
}
}
class Single1{
//饿汉式
private Single1() {
// TODO Auto-generatedconstructor stub
}
private static Single1 s = new Single1();
public static Single1 getInstance(){
return s;
}
}
class Single2{
//懒汉式
private static Single2 s = null;
private Single2(){};
public static Single2 getInstance(){
if(s==null){
s=new Single2();
}
return s;
}
}
*建议使用饿汉式,懒汉式在多线程中可能会出现两个对象,可以通过加入锁来保证元素唯一性。
this关键字
特点:this代表其所在函数所属对象的引用。
换言之:this代本类对象的引用。
什么时候使用this关键字呢?
当在函数内需要用到调用该函数的对象时,就用this。(确定是外部参数或者内部参数)
super关键字
1,super和this的用法相同。
2,this代表本类引用。
3,super代表父类引用。
4,当子父类出现相同的成员名时,可以用super进行区分。
5,子类要调用父类构造函数时,可以使用super语句。
6,super必须放在第一句
代码示例:
package com.itheima;
public class PersonDemo2 {
public static void main(String[] args) {
//创建一个person,并且赋予姓名和年龄
Person2 p = new Person2("zhangsan", 20);
//调用person的eat方法。
p.eat();
}
}
class Person2{
//描述一个人,人都有姓名,年龄等等。。
//定义人的姓名
String name;
//定义人的年龄
int age;
//在创建一个人时便要给人赋予姓名年龄等属性。
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
//人还有吃饭等行为
public void eat() {
// TODO Auto-generatedmethod stub
System.out.println(name+"eatting..");
}
}
static(静态)关键字
用法:是一个修饰符,用于修饰类成员(成员变量,成员函数)
当成员变量被静态修饰后,就多了一个调用方式,除了可以被对象调用外还可以直接被类名调用。à类名.静态成员
static关键字:用于修饰成员(成员变量和成员函数)
static特点
1, 随着类加载而加载
a) 也就是说静态会随着类的消失而消失,所以它的生命周期最长。
2, 优先于对象存在
a) 明确一点:静态时先存在,对象是后存在的。
3,被所有的对象所共享。
4, 可以直接被类名调用。
示例变量和类变量的区别:
1, 存放位置:
a) 类变量随着类的加载而存在于方法区中。
b) 实例变量随着对象的建立而存在于堆内存中。
2, 生命周期:
a) 类变量生命周期最长,随着类的消失而消失。
b) 实例变量生命周期随着对象的消失而消失。
静态使用注意事项
1, 静态方法只能访问静态成员,包括方法和变量。非静态方法即可以访问静态成员又可以访问非静态成员。
2, 静态方法中不可以定义this,super关键字,因为静态优先于对象存在,所以静态方法不可以出现this,super。
3, 主函数是静态的。
静态的利与弊
利:
1,对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象都存储一份。
2,可以直接被类调用。
弊:
1, 生命周期长。
2, 访问出现局限性(只能访问静态。)
静态代码块:
格式:
static{
静态代码块中的执行语句。
}
特点:随着类的加载而执行,只执行一次,并优先于主函数,用于给类进行初始化。
构造代码块:
直接写在类中的代码块:
优先于构造方法执行,每次实例化对象之前都会执行构造代码块。
那么在程序运行中哪个代码块会先运行呢?进行一个小实验:
package com.itheima;
public class MethodDemo2 {
public static void main(String[] args) {
new Demo6();
new Demo6();//再次创建对象,发现静态代码块只运行一次。
}
}
class Demo6{
public Demo6() {
// TODO Auto-generatedconstructor stub
System.out.println("构造方法运行");
}
{
System.out.println("构造方法 块运行");
}
static{
System.out.println("静态代码块运行");
}
}
/*静态代码块运行
构造方法 块运行
构造方法运行
构造方法 块运行
构造方法运行
*/
可以看出 静态代码块>构造方法块>构造方法
继承
继承的概述
1, 多个类中存在相同属性和行为时,这些内容抽取到单独一个类中,那么多个类无需再定义这些内容抽取到单独一个类中,那么多个类无须再定义这些属性和行为,只要继承单独的那个类即可。
2, 多个类可以称为子类,单独这个类被称为父类或超类。
3, 子类可以直接访问父类中的非私有的属性和行为。
4, 通过extends关键字,让类与类之间产生继承关系。
class SubDemo extends Demo{}
5, 继承的出现提高了代码的复用性。
6, 继承的出现让类与类之间产生了关系,提供了多态的前提。
继承的特点:
1, java只支持单继承,不支持多继承(接口支持。)
a) 一个类只能有一个父类,不可以有多个父类(因为会出现jvm不知道执行谁的方法。)
class subDemo extends Demo{}//OK
class subDemo extends Demo1,Demo2//Error
2, java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
3, 定义继承需要注意:
a) 不要仅为了获取其他类中某个功能而去继承。
b) 类与类之间要有所属(”is a”),xx1 是 xx2的一种。
函数覆盖
1, 子类中出现与父类一模一样方法时,会出现覆盖操作,也称为重写或复写。
2, 父类中的私有方法不可以被覆盖。
3, 在子类覆盖方法中,继续使用被覆盖的方法可以通过super函数名获取。
4, 覆盖注意事项:
a) 覆盖时,子类方法权限一定要大于或等于护理类方法权限。
b) 静态只能覆盖静态。
5, 覆盖的应用:
a) 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类中专有的内容。
子类的实例化过程
1, 子类中所有的构造函数默认都会访问父类中空参数的构造函数。
2, 因为每一个构造函数的第一行都有个默认的语句:super();
3, 子类会具备父类中的数据,所有要先明确父类是如何对这些数据进行初始化的。
4, 当父类中没有空参数的构造函数时,子类的构造函数必须通过this或super语句指定要访问的构造函数。
5, 当子类继承父类后,每当运行子类父类的无参构造函数都会运行一次。
package com.itheima;
public class ExtendsDemo {
public static void main(String[] args) {
Zi z= new Zi();
z.eat();
z.sleep();
z.getId();
}
}
class Fu{
public int id = 12345;
public Fu() {
// TODO Auto-generatedconstructor stub
System.out.println("furun..");
}
public void eat(){
System.out.println("fueat");
}
}
class Zi extends Fu{
public int id = 54321;
public Zi() {
// TODO Auto-generatedconstructor stub
System.out.println("zirun..");
}
public void eat(){
System.out.println("zieat");
}
public void sleep(){
System.out.println("zisleep");
}
public void getId(){
System.out.println("zi id ="+this.id);
System.out.println("fu id ="+super.id);
}
}
/*fu run..
zi run..
zi eat
zi sleep
zi id = 54321
fu id = 12345
*/
final关键字
1, final可以修饰类,方法,变量。
2, final修饰的类不可以被继承。
3, final修饰的方法不可以被覆盖。
4, final修饰的变量是一个常量,只能被赋值一次。
5, 内部类只能访问被final修饰的局部变量。
多态
多态:指同一个实体同时具有多种形式
就像是动物,狗,猫等都是动物,动物的多种心态。
当Zi extends Fu 时
Fu f = new Zi();
多态的作用:
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
示例:
package com.itheima;
public class ExtendsDemo2 {
public static void main(String[] args) {
Dog d = new HaShiQi();
d.eat();
}
}
class Dog{
public void eat(){
System.out.println("dog eat");
}
}
class HaShiQi extends Dog{
public void eat(){
System.out.println("HaShiQieat");
}
}
class ZhangAo extends Dog{
public void eat(){
System.out.println("ZhangAoeat");
}
}
基本数据类型
基本数据类型的包装类
java中共有8中基本数据类型:
基本数据类型和其对应的包装类如下图:
8个类都是final修饰的(不可被继承)。
基本数据类型转换为包装类
把基本数据类型→ 包装类:
通过对应包装类的构造方法实现
除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。
包装类→ 基本数据类型
包装类的实例方法xxxValue(); // xxx表示包装类对应的基本数据类型
自jdk1.5后java研发出了一种新功能à自动拆箱装箱。
自动装箱:可把一个基本类型变量直接赋给对应的包装类对象或则Object对象
自动拆箱:允许把 包装类对象直接赋给对应的基本数据类型
示例:
Integer i = 3;//装箱
int i2 = i;//拆箱
继承—抽象类
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。
但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。
抽象类概述
1, 抽象定义
a) 抽象就是从多个事物中将共性的本质的内容抽取出来的。
例如:狼和狗都是犬科动物,犬科就是抽象出来的概念。
2, 抽象类:
a) java中可以定义没有方法体的方法,该方法的具体实现是由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
3, 抽象方法的由来:
a) 多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
例如:狼和狗都有吼叫的方法,可以吼叫的内容是不一样的,所以抽象出来的犬科虽然有吼叫的方法但是却不明确吼叫的细节。
抽象类的特点:
1, 抽象类和抽象方法必须用abstract关键字来修饰。
2, 抽象方法只有一个方法声明,没有方法体,定义在抽象类中。
格式:修饰符abstract返回值类型 函数名(参数列表);
abstract void setDog(String name){}
3, 抽象类不可以被实例化,也就是不可以用new创建对象,原因如下:
抽象类是具体事务抽取出来的,本身并不具备的,没有对应的实例,例如犬科只是一个抽象的概念,真正存在的是狼和狗,而且抽象类即使创建了对象,调用抽象方法也没有意义。
4, 抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则子类也是抽象类。
抽象类不过是一个或多个抽象方法的类而已,有自己的构造函数,当有abstract抽象关键字时,不能喝private,final,static共存,原因如下:
1, private:因为abstract方法需要被重写,所以不能修饰为private。
2, final:因为abstract方法需要被重写,被final修饰的方法是不能被重写的,所以不能同final共存。
3, static:因为abstract方法没有方法体,静态方法需要对方法体执行内容分配空间,所以不能同static共存。
抽象类实例:
package com.itheima;
public class abstractTest {
public static void main(String[] args) {
Demo4 d = new Demo4();
d.setName("zhangsan");
d.show();
System.out.println(d);
}
}
abstract class abstractDemo{
//创建一个抽象方法。
abstract void setName(String name);
abstract String getName();
//抽象方法中可以定义非抽象方法。
public void show(){
System.out.println("abstractshow");
}
}
class Demo4 extends abstractDemo{
//要实现父类抽象方法。
String name;
void setName(String name) {
// TODO Auto-generatedmethod stub
this.name= name;
}
String getName() {
// TODO Auto-generatedmethod stub
return name;
}
@Override
public String toString() {
return "Demo4[name=" + name + "]";
}
}
继承—接口
抽象类是从多个类中抽象出来的模板,若要将这种抽象进行得更彻底,就得用到一种特殊的“抽象类”→接口;
1, 格式:
a) interface Xxx{}
2, 接口中的成员修饰符是固定的。
a) 成员变量:public static final
b) 成员函数:public abstract
3, 接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。
接口的特点
1, 接口是对外暴露的规则
2, 接口是程序的功能扩展。
3, 接口可以用来多实现。
4, 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
5, 接口与接口之间可以有继承关系。
示例:
package com.itheima;
public class InterfaceDemo {
public static void main(String[] args) {
new Demo5().show();
}
}
interface Inter1{
public static final int NUM =1;
public abstract void show();
}
interface Inter2{
// public static final int NUM = 3;
public abstract void show();
}
class Demo5 implements Inter1,Inter2{
@Override
public void show() {
// TODO Auto-generatedmethod stub
System.out.println(NUM);
}
}
内部类:
将一个类定义在另一个类里面,对里面那个类就称为内部类(内置类,嵌套类)
访问特点:
内部类可以直接访问外部类中的成员,包括私有成员。
而外部类要访问内部类中的成员必须要建立内部类的对象。
内部类的位置
1,内部类定义在成员位置上,可以被private,static成员修饰符所修饰。
被static修饰的内部类只能访问外部类中的静态成员。
2,内部类定义在局部位置上,也可以直接访问外部类的成员。
同时可以访问所在局部中的局部变量,但必须是被final修饰的。
匿名内部类
就是内部类的一种简化写法,和匿名方法一样,可以调用其中的方法等等,但是无法有实例化对象。并且匿名内部类必须是继承或者实现一个外部类或者接口。格式为:
new外部类名或接口名(){覆盖类或者接口中的代码(也可理解为自定义对象)}
简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。
示例:
package com.itheima;
public class InnerClassDemo {
public static void main(String[] args) {
new Outer().Method();
//访问非静态内部类中方法。
new Outer.Inner2().show();
new Outer().Method2();
}
}
class Outer extends Dog{
private int x = 4;
private class Inner{//创建一个私有化内部类。
int x = 6;
void show(){
//内部内访问内部变量和外部变量。
System.out.println("inner x ="+this.x+" Outer x ="+new Outer().x);
}
}
static class Inner2{//静态内部类
void show(){
System.out.println("inner2show");
}
}
void Method(){
Inner in = new Inner();
in.show();
}
void Method2(){
new Dog()
{
int num= 9;
void show()
{
System.out.println("dog shownum = "+num);
}
}.show();
}
}