Java从小白到大佬(面向对象第二部分)
1.创建对象的具体流程
1.javac xxx.java 将源代码进行编译,生成若干个字节码文件(.class)
2.java xxx 将名为xxx的.class文件和其相关的.class文件加载到虚拟机中等待运行(具体加载到方法区)
3.虚拟机在静态方法去中找xxx这个字节码中的静态主函数(main),如果没有直接报错(没有主函数函数无法执行);如果有则将主函数的代码加载到栈中,然后开始程序的运行
函数由虚拟机直接调用,不需要创建对象调用
4.在栈里面的函数空间中 拆关键引用数据类型的变量
5.在堆内存中开辟空间,分配地址,准备创建对象
6.对成员变量进行默认初始化
7.相应构造函数进栈,同时对成员变量进行显示初始化
8.按照构造函数的内容,对成员变量进行针对性初始化
9.构造函数弹栈,将对象空间的地址分给变量
2.代码块{}
2.1.静态代码块
格式:
static { 函数体; }
静态代码块随着类的加载只执行一次,且优先于构造函数执行。所以静态代码块有时候可以用来处理一些成员变量。
2.2.构造代码块
{ 方法体; }
构造代码块随着对象的加载,创建一次执行一次。
2.3.局部代码块
函数和语句都叫局部代码块;
3.继承
java面向对象的三大特点:封装,继承,多态
3.1.什么时候可以继承?
当我们在描述一些事物时,发现有些事物具有重复的属性和行为,那么就可以将这些重复的东西进行抽取。
抽取出来的类:父类
原来的类: 子类
两者的关系:子类继承于父类
所有类的最终父类都为object类
3.1.1.代码实现继承要用到super关键字
有一个(父类)图形类figure,一个圆类circle(子类),所有图形都有一个名字name,所有的图形都有计算周长的方法getPerimeter();
class Figure{ String name; public void getPerimeter(); } class Circle extends Figure{ public Figure(){//创建无参构造函数 String name=super.name;//调用父类的变量 super.getPerimeter();//调用父类的方法 } }
注意:
1.java中的类只能是单继承关系,只有接口可以多继承
2.不要随意的继承其他类,避免逻辑错误
3.在继承时变量支持就近引用。(子类局部>子类成员>子类静态>父类成员>父类静态)
3.1.1.1.super关键字的说明
super关键字的用法与this相同,但是super关键字不代表父类对象的引用,他只代表父类在堆方法区的存储位置。
3.1.2.注意事项
1.如果父类的构造函数private私有化,子类无法创建对象
解决:父类必须提供一个子类能够访问的构造函数
2.如果父类的构造函数被显示初始化,子类与父类中不一样的构造函数则无法继承父类
解决:子类得写出来一个与父类一样的构造函数
3.子类对父类继承的函数在子类中实现,其实就是子类对方法的重写。
3.1.2.1.重写的目的
子类对父类的函数有改进或者功能有增强
重写时子类的权限要高于父类:public>protected>默认>private
静态成员函数不存在重写
3.2.栈的两种实现(线性栈/链栈)
3.2.1.线性栈
代码实现:
public class StackDemo { public static void main(String[] args) { Array arr=new Array(); arr.print(); for(int i=0;i<6;i++) { arr.push(i); } arr.print(); } } class function{ public void push(int ele) {};//一个元素进栈 public int pop() {return -1;}; //一个元素出栈 public int peek() {return -1;};//获取当前栈顶元素 public int size() {return -1;};//获取当前数组的有效长度 public void clear() {};//清空当前栈 public void print() {};//打印栈类元素 } class Array extends function{ private int size;//数组的有效长度 int [] array;//容器 public Array() { this(10);//如果创建有参对象则capacity为有参对象创建时传入的值,如果没有则capacity=10 } public Array(int capacity) { array=new int[capacity]; this.size=0; } public void push(int ele) { if(size==array.length) { resize(array.length*2); } array[size]=ele; size++; } public int peek() { return array[size-1]; } public int getCapacity() { return array.length; } public void print() { if(size==0) { System.out.println("bottom[]top :"+size()+"/"+getCapacity()); }else { for(int i=0;i<size;i++) { if(i==0) { System.out.print("["+array[i]+","); }else if(i==size-1) { System.out.print(array[i]+"]"); }else { System.out.print(array[i]+","); } } } } public int pop() { if(size==0) { System.out.println("栈为空!"); return -1; } int ele=array[size-1]; size--; return ele; } public int size() { return size; } public void clear() { size=0; int [] newArr=new int [0]; array=newArr; } private void resize(int num) { int [] newArray=new int[num]; for(int i=0;i<Math.min(array.length, newArray.length);i++) { newArray[i]=array[i]; } array=newArray; } }
3.2.2.链栈
代码:
public class StackDemo { public static void main(String[] args) { Link l=new Link(); for(int i=1;i<10;i++) { l.push(i); } l.print(); } } abstract class function{ abstract public void push(int ele);//一个元素进栈 abstract public int pop() ; //一个元素出栈 abstract public int peek();//获取当前栈顶元素 abstract public int size();//获取当前数组的有效长度 abstract public void clear();//清空当前栈 abstract public void print();//打印栈类元素 } class Link extends function { private int size; private Node head; public Link() { this.size=0; this.head=new Node();//初始化头结点(头结点不需要传数值,只需要知道下一跳的地址) } /*public Link(int [] list) { this();//无参构造器初始化,就是将头结点初始化 //串链表 for(int i=1;i<10;i++) { push(list[i]); } }*/ public void push(int e) { Node p=new Node(e,null);//创建链表元素p p.next=head.next; head.next=p; //head.next=new Node(e,head.next) size++; } private boolean isEmpty() {//判断栈是否为空? if(size==0&&head.next==null) { return true; }else { return false; } } public int pop() { if(isEmpty()) { System.out.println("栈为空!"); return -1; } Node p=head.next; int e=p.ele; head.next=head.next.next; p=null; return e; } public int peek() { return isEmpty()?-1:head.next.ele; } public int size() { return size; } public void clear() { head=null; size=0; } public void print() { if(isEmpty()) { System. 29f1a out.println("栈为空"); }else { String s="top ["; Node p=head; while(true) { if(p.next!=null) { s=s+p.ele+","; p=p.next; }else { s=s+p.ele+"] bottom"; break; } } System.out.println(s); } } } class Node{ int ele; Node next; public Node() { this.ele=0; this.next=null; } public Node(int ele,Node next) { this.ele=ele; this.next=next; } }
3.3.抽象类
3.3.1.什么是抽象类?
在继承的层次结构中,每一个新的子类都使类变得越来越明确和具体。如果从一个类追溯到父类,类有时候就会变得不合乎日常逻辑。类的设计应该确保父类包含子类的所有特征。有时候一个父类设计的非常抽象,以至于没有任何具体的实例,这样的类叫做抽象类。
一般的抽象类的格式:
权限修饰符 abstract class 抽象类名{ 权限修饰符 abstract 函数(); }
3.3.2.特征
抽象类必须含有抽象函数,类名前必须有abstract, 子类有两种情况:要么在类中实现抽象方法,要么也写成抽象类。
将类的实现和使用分离(比如说有一个风扇父类,有好多的风扇子类,每个风扇都可以吹风但是每个风扇吹出来的风速不一样, 则风扇父类就可以抽取这个吹风功能) abstract class fan{//fan类为抽象类 public abstract void chuifeng(); } class fan1 extends fan{ public void chuifeng(){ System.out.println(); } }
注意:父类抽出了几个抽象函数,子类在实现的时候应该有完全相同的函数(此处子类的函数其实是对父类函数的重写)
注意事项:
1.抽象类有构造函数,有成员变量,有成员函数,有静态函数和静态变量
2.抽象类不可以创建对象(但是不代表不能创建对象)
3.抽象类和一般类的区别在于:抽象类有abstract关键字和抽象函数
4.抽象类不能和那些关键字共存?
final 修饰函数表示函数不可以被重写 修饰类表示类不能被继承
private 私有化之后不能被其他类所调用
static 静态不能被重写 由于静态优先于对象加载进方法区
3.4.接口interface
接口是一种和类相似的结构,只包含常量和抽象函数。即当一个抽象类中所有的函数都是抽象函数,则可以用接口表示
接口在许多方面和抽象类相似,但是接口的目的是指明相关或者不相关的类的多个对象的共同行为。
一般格式:
修饰符 interface 接口名{ /** 常量声明 */public static final 变量名; /** 方法签名*/ }
3.4.1.接口创建的规范
1.所有的变量都是public static final
2.没有构造方法,接口不能用new实例化
3.所有方法都是公共的抽象实例方法
4.类A调用接口B之后就相当于A是B的子类,这种情况下可以将接口看成是一个抽象类
3.4.2.调用接口implements
如果有一个接口A,接口B已经被定义,则类word调用接口A和B为: class word implements A,B{ }
1.类与类之间有单继承关系,即一个子类只能继承一个父类
2.类与接口之间有多实现关系,即一个类可以使用多个接口
2.接口与接口之间有多继承关系,即一个接口可以使用多个其他接口
3.4.3.匿名实现子类的匿名对象
对于如下代码所示,Button类是一个手机APP开关类,开关只会在当前情况下使用一次,所以使用匿名实现子类的匿名对象比较合适。
3.5.多态
这里我们要明白,一个类实际上是在定义一种类型。子类定义的类型称为子类型,父类定义的类型称为父类型,继承关系使得一个子类继承父类的特征,并可以附加一些新的特征。每个子类的实例都是其父类的实例,但是父类的实例不一定会是子类的实例。比如:每一个圆都是一个集合对象,但是不是每一个几何对象都是圆。
所以,多态意味着父类型的变量可以引用子类型的对象。且多态一定是在有继承关系的类实现的。
格式:
父类型 变量名=new 子类型();
Geometic circle=new Circle();//这里的circle指的是Circle类创建出来的对象的引用 class Geometic{} class Circle extends Geometic{}
注意:
1.成员变量在多态中的特点:只能访问父类的成员变量
2.成员函数在多态中的特点:如果子类有重写函数,则调用子类重写的函数;如果没有则调用父类的函数。子类的特有不可被调用
3.静态变量在多态中的特点:只能访问父类的静态变量
4.静态函数在多态中的特点:只能访问父类中的静态函数
3.5.1.单线程下的单例模式
单例模式:该类只能创建一个对象
1.外界不能直接创建对象-构造函数私有化
2.对象在内部创建,即在内部new 对象。
3.由于该对象有时候需要外部访问,需要get
4.getXXX不能为成员函数,所以必须static
3.5.1.1.饿汉式
main(){ Demo d1=Demo.getDemo(); Demo d2=Demo.getDemo(); System.out.println(d1==d2);//输出true 因为全局Demo只创建出来一个对象d } class Demo{ private static Demo d=new Demo();//保证全局只有一个对象d private Demo(){}//构造函数私有化 public static Demo getDemo(){ //成员函数静态化,保证getDemo()不会成为成员函数。 return d;//返回对象d } }
3.5.1.2.饱汉式
class Single{ private static Single s=null; //对对象s做一次判断 private Single(){} public static Single getSingle(){ if(s==null){ s=new Single(); }else{ return s; } } }
3.5.2.代理模式
类Agency和类Bb之间有一个类Aa联系,Aa作为中间人知道Bb的一切,那么就可以在Agency中创建Aa的对象指向Bb(Cc同理)
package inHerit; public class Agency { public static void main(String[] args) { Aa a=new Aa(); a.run(); } } class Aa implements X{ Bb b=new Bb(); public void run() { b.run(); } } class Bb implements X{ Cc c=new Cc(); public void run() { c.run(); System.out.println("B can run"); } } class Cc implements X{ public void run() { System.out.println("C can run"); } } interface X{ public void run(); }
3.5.3.内部类
在描述一个事物A(class A)的时候发现A之中还有另一个事物a(class a),则将a称为内部类
class A{ class B{ } }
注意:
1.内部类为外部类的非静态成员
2.内部类中一旦有静态(不管是静态函数还是静态变量),则内部类必须是静态
class Outer{ int num=10; static class Inter{ int num=20; static void show() { int num=30; System.out.println(num); } } }
- java面向对象总结第二部分
- 黑马程序员--面向对象第二部分-内部类、异常--java学习日记6(基础知识)
- Java温习——面向对象第二部分
- [零基础学JAVA]Java SE面向对象部分-14.面向对象高级(02) 推荐
- [零基础学JAVA]Java SE面向对象部分-15.面向对象高级(03)
- [零基础学JAVA]Java SE面向对象部分-12.面向对象基础(07) 推荐
- [零基础学JAVA]Java SE面向对象部分-16.面向对象高级(04) 推荐
- 第二部分 Windows编程、面向对象程序设计
- [零基础学JAVA]Java SE面向对象部分.面向对象基础(02)
- [零基础学JAVA]Java SE面向对象部分.面向对象基础(06)
- [零基础学JAVA]Java SE面向对象部分-08.面向对象基础(03)
- 【小白的java成长系列】——面向对象基础
- [零基础学JAVA]Java SE面向对象部分.面向对象基础(01)
- [零基础学JAVA]Java SE面向对象部分-17.面向对象高级(05)
- Java第二课 Java面向对象编程,面向对象编程和面向过程编程的区别,我们如何才能掌握面向对象的编程,类和对象的关系;讲解了Java中的构造、重载、this和super变量、静态变量、Java中的常
- 第三讲 Java的面向对象特征(继续基础部分......)
- 用Eclipse + CDT + MinGW做Windows编程第二部分:Windows编程、面向对象程序设计
- [零基础学JAVA]Java SE面向对象部分-20.异常的捕获与处理 推荐
- [零基础学JAVA]Java SE面向对象部分-21.包及访问权限 推荐
- [零基础学JAVA]Java SE面向对象部分.面向对象基础(03)