黑马程序员_面向对象2
2014-05-05 18:18
176 查看
----------------------android培训、java培训、期待与您交流! ----------------------
继承(inherit)
1.什么是继承
当定义一个类的时候,如果发现当前类需要使用另一个类中的功能,这时当前类代表的事物是另一个类的子级的时候,就可以继承另一个类
2.怎么继承
定义类的时候可以在类名后面使用extends关键字指定继承另一个类
这时子类会得到父类中的所有成员
使用继承的类叫子类(派生类),被继承的类叫父类(超类,基类)
3.继承的特点
子类继承父类将得到父类所有的可见成员。父类不能得到子类的
一个父类可以有多个子类,一个子类只有一个父类
可以多重继承,一个子类只有一个父类,这时子类能得到父类和父类的父类中的所有功能
4.继承的原理
在创建子类对象的时候,会先加载父类,再加载子类
先创建父类对象,再创建子类对象,创建子类对象的时候,会默认调用父类的构造函数
访问成员的时候,先找子类,再找父类
5.父类的构造函数
在构造函数的第一条语句,要么是当前类构造函数this().要么是父类的构造函数super()
如果没写this()也没写super(),那么就会自动生成一个super(),默认调用父类无参构造函数
原因:创建子类对象需要创建父类对象,没指定用哪个构造函数,默认使用父类中的构造函数
注意:如果父类没有无参的构造函数,那么定义子类的时候,必须显式声明一个构造函数,内部调用父类有参的构造函数
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class Demo {
public static void main(String[] args) {
new C();
new C(123);
}
}
class A {
static {
System.out.println(1);
}
A() {
System.out.println(2);
}
A(int i) {
this();
System.out.println(3);
}
}
class B extends A {
static{
System.out.println(4);
}
B(){
super(123);
System.out.println(5);
}
B(int i) {
this();
System.out.println(6);
}
}
class C extends B {
static {
System.out.println(7);
}
C() {
super(123);
System.out.println(8);
}
C(int i) {
super();
System.out.println(9);
}
}
上述代码的打印结果:14723568 2359
6.子类重写(override)父类的方法
当子类继承父类的时候,子类会得到父类的所有可见方法
这时子类中可以和父类定义一个一摸一样(返回值类型,方法名,参数列表)的方法,这就叫重写
当子类重写父类方法之后,再次调用时,就会调用子类的方法
重写父类方法后,如果还想调用父类的方法,那么就可以使用super.方法名调用
7.@Override(重写)
在重写父类方法的时候,最好加上这个注释
加上他之后,如果没有重写成功,就会编译报错,提高代码的安全性
8.向上转型
子类继承父类之后,将得到父类的所有功能,所以子类对象可以当作父类对象使用
注意:父类不能当作子类来用,因为子类特有的方法父类没有,子类的子类也可以当作父类来用
9.子类当父类用时,成员访问的问题
父类变量引用子类对象时
调用方法:优先找子类的(无论变量是什么类型),为了更好的支持多态
访问成员变量:就看引用是哪个类型,就在哪个类型中找。(因为一般来说变量都声明为私有,这条没什么用)
10.强制类型转换
子类对象当作父类来用时,不能通过父类变量调用父类中没有的方法
如果子类拥有该方法,那么可以把父类变量强转成子类,这种方法有可能出问题
强制类型转换时, 只要两个类有父子关系, 编译不报错. 但是如果类型不匹配: ClassCastException
检查变量a是否是B类类型:if(a instanceof B)
Object类
1.什么是Object类
Object类是所有Java类的父类,当我们定义一个类的时候,如果没有继承任何类,那么默认就是继承Object类
Object类中的所有方法,都会被任何一个Java类继承
Java语言中所有类都是Object的子类,包括数组,但是基础数据类型不是(自动装箱后的基本数据类型是Object的子类)
int i = 123; System.out.println(i.toString());//编译出错
2.toString()方法
返回该对象的字符串表示,Object类默认返回类名@地址,建议所有子类都重写此方法
对象在和字符串做加法运算时,也会默认调用toString方法
3.equals()
==比较两个对象的地址,判断是否是指向同一个对象
Object类中默认的equals方法比较的是地址,建议重写equals方法,可以用来比较变量指向的对象中的内容是否相同
String类的equals方法JDK中已经重写
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
<span style="white-space:pre"> </span>String str = "ddd";
String str1 = new String("ddd");
str.equals(str1); //返回true
重写equals方法:
public boolean equals(Object obj) { //多态
if(this == obj) //如果地址相同就直接返回true
return true;
if(!(obj instanceof Person)) //判断是否为Person类
return false;
Person other = (Person)obj; //为了访问Person类的成员变量,强转Object类
//if(this.name != other.name) 不安全,Person p1 = new Person("fal",4);Person p2 = new Person(new String("fal"),4);
if(this.name == null) { //防止空指针异常
if(other.name != null)
return false;
}
else if(!this.name.equals(other.name))
return false;
if(this.age != other.age)
return false;
return true;
}
4.finalize() //使完成,使结束
在对象生命周期结束(成为垃圾对象,并且被销毁)之后,自动调用该方法
如果我们希望在对象被销毁的时候想做一些事情,就可以重写finalize()方法
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class FinalizeDemo {
public static void main(String[] args) throws Exception {
A a = new A();
a = null;
for (int i = 0; i < 1000; i++)
new A();
System.gc(); // 虚拟机在垃圾对象特别多的时候, 才会销毁, 如果我们希望立即销毁, 可以调用
Thread.sleep(1000); // 让程序休眠1000毫秒, 等待销毁完成
}
}
class A {
public void finalize() {
System.out.println("对象被销毁了!!!"); // 如果该对象占用资源或者打开某个链接, 在销毁的时候就应该释放掉
}
}
多态
1.什么是多态
一段代码可以运行出多种形态,用父类变量引用子类对象
调用方法时引用的是哪个子类对象,就调哪个类中的方法
2.怎么使用
在定义函数的的时候,形参定义成父类类型,使用父类变量调用方法
这样就不用为每个子类定义方法调用,提高代码的复用性和可维护性
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class Driver {
public void drive(Car car) { //多态
car.run();
}
}
class Car {
public void run() {
}
}
class Benz extends Car{
public void run() { //重写父类的方法
System.out.println("this is Benz");
}
}
class Bmw extends Car{
public void run() {
System.out.println("this is Bmw");
}
}
class Demo{
public static void main(String[] args) {
Driver d = new Driver();
d.drive(new Benz()); //父类引用指向子类对象
}
}
抽象类
1.什么是抽象类
抽象类就是用abstract关键字修饰的类
抽象类不能创建对象,它的作用就是把若干子类中的方法抽取出来定义在父类中
抽象类可以有抽象方法,有抽象方法的类必须是抽象类
2.什么是抽象方法
抽象方法就是用abstract关键字修饰的方法
抽象方法没有方法体,只有"修饰符 返回值类型 方法名(参数列表)"
抽象方法代表子类都有这个方法,但是具体实现不同
3.什么时候使用抽象类
在多个类都有相同的方法声明,并且多个类都是某一类事物的子集时,就应该定义父类
多个子类中相同的方法,可以直接在父类中定义,子类直接继承
多个子类中不同的方法,无法在父类中定义出来,但是可以定义成抽象方法
4.继承抽象类
定义一个抽象类的子类时,必须实现所有的抽象方法,除非子类也是抽象方法
5.方法重写要求
返回值类型,方法名,参数列表都一样
重写的方法的访问权限不能小于被重写的方法 public>protected>default>private
如果子类的返回值类型是父类返回值类型的子类,也可以
子类重写时不能抛出父类没有声明的异常
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//抽象类
abstract class Student
{
private String name;
abstract void study();//抽象方法为子类提供模版,有抽象方法的类一定是抽象类
public void run() //抽象类中可以定义非抽象方法
{
}
}
class BaseStudent extends Student
{
public void study() //子类必须覆盖父类的抽象方法,否则子类也该为抽象类
{
System.out.println("base study");
}
}
class AdvStudent extends Student
{
public void study()
{
System.out.println("advance study");
}
}
class Demo
{
public static void main(String[] args)
{
/*Student是抽象的无法实例化
Student stu = new Student();
*/
BaseStudent baseStu = new BaseStudent();
AdvStudent advStu = new AdvStudent();
baseStu.study();
advStu.study();
}
}
接口
1.什么是接口
接口是一种特殊的抽象类,接口中的方法全部是抽象的(JDK8之前)
一个类只能继承一个抽象类,但是可以实现多个接口
2.接口和抽象类的区别
抽象类用abstract修饰,接口用interface定义
抽象类中可以有不抽象的方法,接口中的方法都是抽象的
抽象类用extends继承,接口用implements实现
抽象类中的方法没有默认修饰符,接口中的方法默认是被public abstract修饰的
3.什么情况下用接口,什么情况下使用抽象类
在定义一个类的时候,如果需要定义抽象方法,那么就需要使用抽象类或接口
如果该类中还有不抽象的方法,那么就只能使用抽象类
其他情况尽量使用接口,因为接口不占用继承位置,子类实现接口的同时还能继承其他类
4.实现接口
两个接口中有有方法名相同,参数列表相同,但返回值类型不同的方法时不能同时继承这两个接口
实现接口和继承抽象类相同,必须实现所有的抽象方法、
除非是抽象类,可以不实现所有的方法
接口和接口之间可以互相继承,并且可以继承多个
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
interface enter
{
abstract void run();
}
interface enter1
{
void play(); //abstract 可不写默认为抽象方法
}
interface enter2 extends enter,enter1 //接口可以多继承
{
abstract void eat();
}
interface enter3
{
abstract void sleep();
}
class Boy implements enter2,enter3 //多实现
{
public void run() //必须覆盖接口中的抽象方法
{
System.out.println("running");
}
public void play()
{
System.out.println("playing");
}
public void eat()
{
System.out.println("eat");
}
public void sleep() //必须覆盖所有抽象方法
{
System.out.println("sleep");
}
}
class InterfaceTest
{
public static void main(String[] args)
{
Boy boy = new Boy();
boy.sleep();
}
}
final 关键字
1.什么是final
final关键字可以修饰类,方法,变量
被final修饰的类,方法,变量都是最终的,不能修改的
2.final类
使用final修饰一个类,这个类就不能被继承
3.final方法
使用final修饰一个方法,这个方法就不能被重写
4.final变量
使用final修饰一个变量,这个变量就不能被赋值了(只能被赋值一次)
设计模式
1.什么是设计模式
设计模式就是类似棋谱或者共识,在编程的过程中遇到一些特别常见的问题
这些问题被前人总结归纳,经过大量实践证明之后发现的一些比较经典的做法叫做设计模式
2.单例设计模式
如果在设计一个类的时候,希望这个类只有一个对象,那么就可以使用单例设计模式
写法:
a.私有化构造函数,阻止类外创建对象
b.在内部创建一个对象,用成员变量引用
c.提供一个共有的获取对象的方法
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class Singleton {
private Singelton() { //将构造函数私有化,其他类就无法通过构造函数创建对象
}
/*
由于构造函数私有化,因此无法同过new来创建对象
没有对象则无法调用类中的非静态方法,因此把方法声明为静态让类名直接调用返回一个对象
*/
private static Singleton single = new Singleton();
public static Singleton getInstance () {
return single;
}
}
延迟加载的单例
普通的单例设计模式,在类加载的时候就会创建对象
而有的时候只是访问了类中的某个静态成员,而没有获取对象,这样创建就浪费了内存
所以我们可以使用类加载延迟的单例设计,成员变量处不直接创建对象,在第一次调用方法时创建
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class Singleton() {
private static Singleton lazySingle = null;
private Singleton() {
}
public static lazySingle getInstance() {
if (lazySingle == null)
lazySingle = new Singleton();
return lazySingleton
}
3.模版设计模式
在使用程序做一些事情的时候,如果每次都有一些步骤是重复的
那么就可以使用模版设计模式来精简,每次只写不同的地方
写法:
定义一个抽象类用作模版类
在其中定义一个final修饰的模版方法
在方法中把每次都一样的代码写上,每次不同的代码用抽象方法代替
使用的时候,定义类继承模版类,实现抽象方法,写上每次不同的代码
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
abstract class Templete { //定义模版类
public abstract void run(); //其他类需要重写这个方法用来测试时间
public void test() { //定义模版方法,把每次一样的步骤写在里面,每次不一样的代码用抽象方法代替
long time1 = System.currentTimeMillis();
run();
long time2 = System.currentTimeMillis();
System.out.println("time="+(time2 - time1));
}
}
class S extends Templete {
public void run() {
for (int i=0; i<2334343; i++){
}
}
public static void main(String[] args) {
new S().test();
}
}
包package
1.什么是包
平时我们使用的类都是有包的,例如:System,String,Object,他们都是在java.lang包中
Java语言按照功能模块定义了一些包,例如lang,util,io,net,sql,awt
包就是把类分类管理,一个项目中可能会有很多泪,这时就应该定义包分类管理
2.怎么定义包
package pack;
直接用类名创建对象,默认找同一个包中的类
3.编译运行
javac -d 目录 源文件名
java 包名.类名
4.使用其他包中的类
全限定名:可以使用"包名".类名的形式使用一个其他包中的类
星号方式导入包:使用import 包名.*;导入类,这样可以导入包内的所有类
这种导入方式会先在当前包中查找,如果没有,才去导入的包中查找
类名方式导入包:使用import包名.类名方式导入类,明确指定导入一个类
推荐使用类名导入
5.有包类和无包类之间的访问
无包的类可以使用有包的类(直接导入包即可)
有包的类无法使用无包的类(不导包访问同包的,无包的又无法导入)
6.总结
以后写类都要带包,类名和文件名同名,并加上public
导入包的时候要用类名导入
编译加上-d,运行加上包名
面向对象的总结
1.构造函数
如何定义
如何重载
如何互相调用
自动生成构造函数
2.this关键字
当作引用来引用
调用当前类构造函数
3.生命周期
什么时候销毁
4.封装
私有化成员变量
提供公共访问方法
5静态
变量
方法
6.继承
创建对象的原理
父类构造函数的调用
重写父类的方法
子类可以当作父类使用
调用方法找子类
强制类型转换
7.Object
toString()
equals()
内部类
内部类的访问规则:
1.内部类可以直接访问外部类中的成员,包括私有
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
2.外部类访问内部类,必须建立内部类的对象
访问格式:
1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中
可以直接建立内部类对象
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象
2.当内部类在成员位置上,就可以被成员修饰符所修饰
比如private 将内部类在外部类中进行封装
static:内部类就具备静态的特性:当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问限制
外部其他类中直接访问static内部类的非静态成员方式:
new Outer.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员方式:
注意:当内部类中定义了静态成员,该内部类必须是静态的
当外部类中的静态方法访问内部类时,内部类也必须是静态的
内部类定义在局部时:
1.不可以被成员修饰符修饰
2.可以直接访问外部类中的成员,因为还持有外部类中的引用
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量
匿名内部类(定义类和建立对象封装在一起,也就是匿名子类对象):
1.匿名内部类其实就是内部类的简写格式
2.定义匿名内部类的前提
内部类必须是继承一个类或者实现接口
3.匿名内部类的格式:new父类或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象,可以理解为带内容的对象
5.匿名内部类中定义的方法最好不要超过3个
内部类
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class Outer
{
private int x = 3;
private class Inner //私有内部类
{
private int x =4;
void function()
{
int x =5;
System.out.println("outer:"+Outer.this.x); //访问外部类变量
System.out.println("inner"+this.x);//内部类变量
System.out.println(x); //局部变量
}
}
static class Inner1 //静态内部类
{
void function()
{
System.out.println("fds");
}
static void function1()
{
System.out.println("std");
}
}
public void method() //提供外部方法访问内部事物,对内部事物进行封装
{
Inner in = new Inner();
in.function();
}
void show()
{
class Inner2 //局部的内部类,无法定义静态
{
final int y = 4;
void run()//要运行此方法必须创建Inner的对象
{
System.out.println(Outer.this.x);
System.out.println(y);//内部类定义在局部时,只能访问final型的局部变量
}
}
new Inner2().run();
}
}
class Test
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method();
new Outer.Inner1().function();//外部其他类访问静态内部类的非静态成员
Outer.Inner1.function1();//外部其他类访问静态内部类的静态成员
new Outer().show();
}
}
匿名内部类
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
class InnerClassDemo
{
public static void main(String[] args)
{
new Outer().function();
}
}
abstract class AbsDemo //匿名对象的父类
{
abstract void show();
}
class Outer
{
int x = 3;
/*
等同于下面创建匿名对象
class Inner extends AbsDemo //继承了一个类
{
void show() //覆盖
{
System.out.println("show:"+x);
}
}
*/
public void function()
{
//new Inner().show();//创建对象
//AbsDemo d = new AbsDemo() 多态,对象d只能调用show()
new AbsDemo()//创建匿名内部类
{
void show()//匿名对象的成员方法
{
System.out.println("x="+x);
}
void abc()
{
System.out.println("fdf");
}
}.show();//匿名子类对象调用show()方法,一次只能调用一个成员方法
}
}
----------------------android培训、java培训、期待与您交流! ----------------------
继承(inherit)
1.什么是继承
当定义一个类的时候,如果发现当前类需要使用另一个类中的功能,这时当前类代表的事物是另一个类的子级的时候,就可以继承另一个类
2.怎么继承
定义类的时候可以在类名后面使用extends关键字指定继承另一个类
这时子类会得到父类中的所有成员
使用继承的类叫子类(派生类),被继承的类叫父类(超类,基类)
3.继承的特点
子类继承父类将得到父类所有的可见成员。父类不能得到子类的
一个父类可以有多个子类,一个子类只有一个父类
可以多重继承,一个子类只有一个父类,这时子类能得到父类和父类的父类中的所有功能
4.继承的原理
在创建子类对象的时候,会先加载父类,再加载子类
先创建父类对象,再创建子类对象,创建子类对象的时候,会默认调用父类的构造函数
访问成员的时候,先找子类,再找父类
5.父类的构造函数
在构造函数的第一条语句,要么是当前类构造函数this().要么是父类的构造函数super()
如果没写this()也没写super(),那么就会自动生成一个super(),默认调用父类无参构造函数
原因:创建子类对象需要创建父类对象,没指定用哪个构造函数,默认使用父类中的构造函数
注意:如果父类没有无参的构造函数,那么定义子类的时候,必须显式声明一个构造函数,内部调用父类有参的构造函数
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class Demo {
public static void main(String[] args) {
new C();
new C(123);
}
}
class A {
static {
System.out.println(1);
}
A() {
System.out.println(2);
}
A(int i) {
this();
System.out.println(3);
}
}
class B extends A {
static{
System.out.println(4);
}
B(){
super(123);
System.out.println(5);
}
B(int i) {
this();
System.out.println(6);
}
}
class C extends B {
static {
System.out.println(7);
}
C() {
super(123);
System.out.println(8);
}
C(int i) {
super();
System.out.println(9);
}
}
上述代码的打印结果:14723568 2359
6.子类重写(override)父类的方法
当子类继承父类的时候,子类会得到父类的所有可见方法
这时子类中可以和父类定义一个一摸一样(返回值类型,方法名,参数列表)的方法,这就叫重写
当子类重写父类方法之后,再次调用时,就会调用子类的方法
重写父类方法后,如果还想调用父类的方法,那么就可以使用super.方法名调用
7.@Override(重写)
在重写父类方法的时候,最好加上这个注释
加上他之后,如果没有重写成功,就会编译报错,提高代码的安全性
8.向上转型
子类继承父类之后,将得到父类的所有功能,所以子类对象可以当作父类对象使用
注意:父类不能当作子类来用,因为子类特有的方法父类没有,子类的子类也可以当作父类来用
9.子类当父类用时,成员访问的问题
父类变量引用子类对象时
调用方法:优先找子类的(无论变量是什么类型),为了更好的支持多态
访问成员变量:就看引用是哪个类型,就在哪个类型中找。(因为一般来说变量都声明为私有,这条没什么用)
10.强制类型转换
子类对象当作父类来用时,不能通过父类变量调用父类中没有的方法
如果子类拥有该方法,那么可以把父类变量强转成子类,这种方法有可能出问题
强制类型转换时, 只要两个类有父子关系, 编译不报错. 但是如果类型不匹配: ClassCastException
检查变量a是否是B类类型:if(a instanceof B)
Object类
1.什么是Object类
Object类是所有Java类的父类,当我们定义一个类的时候,如果没有继承任何类,那么默认就是继承Object类
Object类中的所有方法,都会被任何一个Java类继承
Java语言中所有类都是Object的子类,包括数组,但是基础数据类型不是(自动装箱后的基本数据类型是Object的子类)
int i = 123; System.out.println(i.toString());//编译出错
2.toString()方法
返回该对象的字符串表示,Object类默认返回类名@地址,建议所有子类都重写此方法
对象在和字符串做加法运算时,也会默认调用toString方法
3.equals()
==比较两个对象的地址,判断是否是指向同一个对象
Object类中默认的equals方法比较的是地址,建议重写equals方法,可以用来比较变量指向的对象中的内容是否相同
String类的equals方法JDK中已经重写
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
<span style="white-space:pre"> </span>String str = "ddd";
String str1 = new String("ddd");
str.equals(str1); //返回true
重写equals方法:
public boolean equals(Object obj) { //多态
if(this == obj) //如果地址相同就直接返回true
return true;
if(!(obj instanceof Person)) //判断是否为Person类
return false;
Person other = (Person)obj; //为了访问Person类的成员变量,强转Object类
//if(this.name != other.name) 不安全,Person p1 = new Person("fal",4);Person p2 = new Person(new String("fal"),4);
if(this.name == null) { //防止空指针异常
if(other.name != null)
return false;
}
else if(!this.name.equals(other.name))
return false;
if(this.age != other.age)
return false;
return true;
}
4.finalize() //使完成,使结束
在对象生命周期结束(成为垃圾对象,并且被销毁)之后,自动调用该方法
如果我们希望在对象被销毁的时候想做一些事情,就可以重写finalize()方法
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class FinalizeDemo {
public static void main(String[] args) throws Exception {
A a = new A();
a = null;
for (int i = 0; i < 1000; i++)
new A();
System.gc(); // 虚拟机在垃圾对象特别多的时候, 才会销毁, 如果我们希望立即销毁, 可以调用
Thread.sleep(1000); // 让程序休眠1000毫秒, 等待销毁完成
}
}
class A {
public void finalize() {
System.out.println("对象被销毁了!!!"); // 如果该对象占用资源或者打开某个链接, 在销毁的时候就应该释放掉
}
}
多态
1.什么是多态
一段代码可以运行出多种形态,用父类变量引用子类对象
调用方法时引用的是哪个子类对象,就调哪个类中的方法
2.怎么使用
在定义函数的的时候,形参定义成父类类型,使用父类变量调用方法
这样就不用为每个子类定义方法调用,提高代码的复用性和可维护性
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class Driver {
public void drive(Car car) { //多态
car.run();
}
}
class Car {
public void run() {
}
}
class Benz extends Car{
public void run() { //重写父类的方法
System.out.println("this is Benz");
}
}
class Bmw extends Car{
public void run() {
System.out.println("this is Bmw");
}
}
class Demo{
public static void main(String[] args) {
Driver d = new Driver();
d.drive(new Benz()); //父类引用指向子类对象
}
}
抽象类
1.什么是抽象类
抽象类就是用abstract关键字修饰的类
抽象类不能创建对象,它的作用就是把若干子类中的方法抽取出来定义在父类中
抽象类可以有抽象方法,有抽象方法的类必须是抽象类
2.什么是抽象方法
抽象方法就是用abstract关键字修饰的方法
抽象方法没有方法体,只有"修饰符 返回值类型 方法名(参数列表)"
抽象方法代表子类都有这个方法,但是具体实现不同
3.什么时候使用抽象类
在多个类都有相同的方法声明,并且多个类都是某一类事物的子集时,就应该定义父类
多个子类中相同的方法,可以直接在父类中定义,子类直接继承
多个子类中不同的方法,无法在父类中定义出来,但是可以定义成抽象方法
4.继承抽象类
定义一个抽象类的子类时,必须实现所有的抽象方法,除非子类也是抽象方法
5.方法重写要求
返回值类型,方法名,参数列表都一样
重写的方法的访问权限不能小于被重写的方法 public>protected>default>private
如果子类的返回值类型是父类返回值类型的子类,也可以
子类重写时不能抛出父类没有声明的异常
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//抽象类
abstract class Student
{
private String name;
abstract void study();//抽象方法为子类提供模版,有抽象方法的类一定是抽象类
public void run() //抽象类中可以定义非抽象方法
{
}
}
class BaseStudent extends Student
{
public void study() //子类必须覆盖父类的抽象方法,否则子类也该为抽象类
{
System.out.println("base study");
}
}
class AdvStudent extends Student
{
public void study()
{
System.out.println("advance study");
}
}
class Demo
{
public static void main(String[] args)
{
/*Student是抽象的无法实例化
Student stu = new Student();
*/
BaseStudent baseStu = new BaseStudent();
AdvStudent advStu = new AdvStudent();
baseStu.study();
advStu.study();
}
}
接口
1.什么是接口
接口是一种特殊的抽象类,接口中的方法全部是抽象的(JDK8之前)
一个类只能继承一个抽象类,但是可以实现多个接口
2.接口和抽象类的区别
抽象类用abstract修饰,接口用interface定义
抽象类中可以有不抽象的方法,接口中的方法都是抽象的
抽象类用extends继承,接口用implements实现
抽象类中的方法没有默认修饰符,接口中的方法默认是被public abstract修饰的
3.什么情况下用接口,什么情况下使用抽象类
在定义一个类的时候,如果需要定义抽象方法,那么就需要使用抽象类或接口
如果该类中还有不抽象的方法,那么就只能使用抽象类
其他情况尽量使用接口,因为接口不占用继承位置,子类实现接口的同时还能继承其他类
4.实现接口
两个接口中有有方法名相同,参数列表相同,但返回值类型不同的方法时不能同时继承这两个接口
实现接口和继承抽象类相同,必须实现所有的抽象方法、
除非是抽象类,可以不实现所有的方法
接口和接口之间可以互相继承,并且可以继承多个
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
interface enter
{
abstract void run();
}
interface enter1
{
void play(); //abstract 可不写默认为抽象方法
}
interface enter2 extends enter,enter1 //接口可以多继承
{
abstract void eat();
}
interface enter3
{
abstract void sleep();
}
class Boy implements enter2,enter3 //多实现
{
public void run() //必须覆盖接口中的抽象方法
{
System.out.println("running");
}
public void play()
{
System.out.println("playing");
}
public void eat()
{
System.out.println("eat");
}
public void sleep() //必须覆盖所有抽象方法
{
System.out.println("sleep");
}
}
class InterfaceTest
{
public static void main(String[] args)
{
Boy boy = new Boy();
boy.sleep();
}
}
final 关键字
1.什么是final
final关键字可以修饰类,方法,变量
被final修饰的类,方法,变量都是最终的,不能修改的
2.final类
使用final修饰一个类,这个类就不能被继承
3.final方法
使用final修饰一个方法,这个方法就不能被重写
4.final变量
使用final修饰一个变量,这个变量就不能被赋值了(只能被赋值一次)
设计模式
1.什么是设计模式
设计模式就是类似棋谱或者共识,在编程的过程中遇到一些特别常见的问题
这些问题被前人总结归纳,经过大量实践证明之后发现的一些比较经典的做法叫做设计模式
2.单例设计模式
如果在设计一个类的时候,希望这个类只有一个对象,那么就可以使用单例设计模式
写法:
a.私有化构造函数,阻止类外创建对象
b.在内部创建一个对象,用成员变量引用
c.提供一个共有的获取对象的方法
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class Singleton {
private Singelton() { //将构造函数私有化,其他类就无法通过构造函数创建对象
}
/*
由于构造函数私有化,因此无法同过new来创建对象
没有对象则无法调用类中的非静态方法,因此把方法声明为静态让类名直接调用返回一个对象
*/
private static Singleton single = new Singleton();
public static Singleton getInstance () {
return single;
}
}
延迟加载的单例
普通的单例设计模式,在类加载的时候就会创建对象
而有的时候只是访问了类中的某个静态成员,而没有获取对象,这样创建就浪费了内存
所以我们可以使用类加载延迟的单例设计,成员变量处不直接创建对象,在第一次调用方法时创建
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class Singleton() {
private static Singleton lazySingle = null;
private Singleton() {
}
public static lazySingle getInstance() {
if (lazySingle == null)
lazySingle = new Singleton();
return lazySingleton
}
3.模版设计模式
在使用程序做一些事情的时候,如果每次都有一些步骤是重复的
那么就可以使用模版设计模式来精简,每次只写不同的地方
写法:
定义一个抽象类用作模版类
在其中定义一个final修饰的模版方法
在方法中把每次都一样的代码写上,每次不同的代码用抽象方法代替
使用的时候,定义类继承模版类,实现抽象方法,写上每次不同的代码
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
abstract class Templete { //定义模版类
public abstract void run(); //其他类需要重写这个方法用来测试时间
public void test() { //定义模版方法,把每次一样的步骤写在里面,每次不一样的代码用抽象方法代替
long time1 = System.currentTimeMillis();
run();
long time2 = System.currentTimeMillis();
System.out.println("time="+(time2 - time1));
}
}
class S extends Templete {
public void run() {
for (int i=0; i<2334343; i++){
}
}
public static void main(String[] args) {
new S().test();
}
}
包package
1.什么是包
平时我们使用的类都是有包的,例如:System,String,Object,他们都是在java.lang包中
Java语言按照功能模块定义了一些包,例如lang,util,io,net,sql,awt
包就是把类分类管理,一个项目中可能会有很多泪,这时就应该定义包分类管理
2.怎么定义包
package pack;
直接用类名创建对象,默认找同一个包中的类
3.编译运行
javac -d 目录 源文件名
java 包名.类名
4.使用其他包中的类
全限定名:可以使用"包名".类名的形式使用一个其他包中的类
星号方式导入包:使用import 包名.*;导入类,这样可以导入包内的所有类
这种导入方式会先在当前包中查找,如果没有,才去导入的包中查找
类名方式导入包:使用import包名.类名方式导入类,明确指定导入一个类
推荐使用类名导入
5.有包类和无包类之间的访问
无包的类可以使用有包的类(直接导入包即可)
有包的类无法使用无包的类(不导包访问同包的,无包的又无法导入)
6.总结
以后写类都要带包,类名和文件名同名,并加上public
导入包的时候要用类名导入
编译加上-d,运行加上包名
面向对象的总结
1.构造函数
如何定义
如何重载
如何互相调用
自动生成构造函数
2.this关键字
当作引用来引用
调用当前类构造函数
3.生命周期
什么时候销毁
4.封装
私有化成员变量
提供公共访问方法
5静态
变量
方法
6.继承
创建对象的原理
父类构造函数的调用
重写父类的方法
子类可以当作父类使用
调用方法找子类
强制类型转换
7.Object
toString()
equals()
内部类
内部类的访问规则:
1.内部类可以直接访问外部类中的成员,包括私有
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
2.外部类访问内部类,必须建立内部类的对象
访问格式:
1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中
可以直接建立内部类对象
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象
2.当内部类在成员位置上,就可以被成员修饰符所修饰
比如private 将内部类在外部类中进行封装
static:内部类就具备静态的特性:当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问限制
外部其他类中直接访问static内部类的非静态成员方式:
new Outer.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员方式:
注意:当内部类中定义了静态成员,该内部类必须是静态的
当外部类中的静态方法访问内部类时,内部类也必须是静态的
内部类定义在局部时:
1.不可以被成员修饰符修饰
2.可以直接访问外部类中的成员,因为还持有外部类中的引用
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量
匿名内部类(定义类和建立对象封装在一起,也就是匿名子类对象):
1.匿名内部类其实就是内部类的简写格式
2.定义匿名内部类的前提
内部类必须是继承一个类或者实现接口
3.匿名内部类的格式:new父类或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象,可以理解为带内容的对象
5.匿名内部类中定义的方法最好不要超过3个
内部类
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class Outer
{
private int x = 3;
private class Inner //私有内部类
{
private int x =4;
void function()
{
int x =5;
System.out.println("outer:"+Outer.this.x); //访问外部类变量
System.out.println("inner"+this.x);//内部类变量
System.out.println(x); //局部变量
}
}
static class Inner1 //静态内部类
{
void function()
{
System.out.println("fds");
}
static void function1()
{
System.out.println("std");
}
}
public void method() //提供外部方法访问内部事物,对内部事物进行封装
{
Inner in = new Inner();
in.function();
}
void show()
{
class Inner2 //局部的内部类,无法定义静态
{
final int y = 4;
void run()//要运行此方法必须创建Inner的对象
{
System.out.println(Outer.this.x);
System.out.println(y);//内部类定义在局部时,只能访问final型的局部变量
}
}
new Inner2().run();
}
}
class Test
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method();
new Outer.Inner1().function();//外部其他类访问静态内部类的非静态成员
Outer.Inner1.function1();//外部其他类访问静态内部类的静态成员
new Outer().show();
}
}
匿名内部类
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
class InnerClassDemo
{
public static void main(String[] args)
{
new Outer().function();
}
}
abstract class AbsDemo //匿名对象的父类
{
abstract void show();
}
class Outer
{
int x = 3;
/*
等同于下面创建匿名对象
class Inner extends AbsDemo //继承了一个类
{
void show() //覆盖
{
System.out.println("show:"+x);
}
}
*/
public void function()
{
//new Inner().show();//创建对象
//AbsDemo d = new AbsDemo() 多态,对象d只能调用show()
new AbsDemo()//创建匿名内部类
{
void show()//匿名对象的成员方法
{
System.out.println("x="+x);
}
void abc()
{
System.out.println("fdf");
}
}.show();//匿名子类对象调用show()方法,一次只能调用一个成员方法
}
}
----------------------android培训、java培训、期待与您交流! ----------------------
相关文章推荐
- 黑马程序员——java面向对象-继承
- 黑马程序员——Objective-C之面向对象基础
- 黑马程序员--面向对象思想的个人理解以及类中成员
- 黑马程序员---面向对象一
- 黑马程序员——Java基础---面向对象(面向对象,类,对象,匿名对象,封装,构造函数,构造代码块,this,static,main,帮助文档,静态代码块,单例)
- 黑马程序员-面向对象-异常处理机制
- 黑马程序员----面向对象1(匿名对象、封装、构造函数、this、static)
- 黑马程序员──面向对象(二)
- 黑马程序员 面向对象
- 黑马程序员__面向对象之多态
- 黑马程序员 ---- 面向对象之多态 Day01
- 黑马程序员-Java面向对象2
- 黑马程序员---OC面向对象总结
- 黑马程序员--oc:面向对象语法
- 黑马程序员--Java面向对象之this、static和单例设计模式
- 黑马程序员-JAVASE入门(面向对象,单例模式)
- 黑马程序员--第一阶段3.面向对象--第7天
- 黑马程序员_面向对象讲解
- 黑马程序员_java_基础_面向对象01
- 黑马程序员_面向对象2