----------------------android培训、java培训、期待与您交流! ----------------------
继承(inherit)
1.什么是继承
当定义一个类的时候,如果发现当前类需要使用另一个类中的功能,这时当前类代表的事物是另一个类的子级的时候,就可以继承另一个类
2.怎么继承
定义类的时候可以在类名后面使用extends关键字指定继承另一个类
这时子类会得到父类中的所有成员
使用继承的类叫子类(派生类),被继承的类叫父类(超类,基类)
3.继承的特点
子类继承父类将得到父类所有的可见成员。父类不能得到子类的
一个父类可以有多个子类,一个子类只有一个父类
可以多重继承,一个子类只有一个父类,这时子类能得到父类和父类的父类中的所有功能
4.继承的原理
在创建子类对象的时候,会先加载父类,再加载子类
先创建父类对象,再创建子类对象,创建子类对象的时候,会默认调用父类的构造函数
访问成员的时候,先找子类,再找父类
5.父类的构造函数
在构造函数的第一条语句,要么是当前类构造函数this().要么是父类的构造函数super()
如果没写this()也没写super(),那么就会自动生成一个super(),默认调用父类无参构造函数
原因:创建子类对象需要创建父类对象,没指定用哪个构造函数,默认使用父类中的构造函数
注意:如果父类没有无参的构造函数,那么定义子类的时候,必须显式声明一个构造函数,内部调用父类有参的构造函数
- 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);
- }
- }
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中已经重写
- <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;
- }
在对象生命周期结束(成为垃圾对象,并且被销毁)之后,自动调用该方法
如果我们希望在对象被销毁的时候想做一些事情,就可以重写finalize()方法
- 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.怎么使用
在定义函数的的时候,形参定义成父类类型,使用父类变量调用方法
这样就不用为每个子类定义方法调用,提高代码的复用性和可维护性
- 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
如果子类的返回值类型是父类返回值类型的子类,也可以
子类重写时不能抛出父类没有声明的异常
- //抽象类
- 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.实现接口
两个接口中有有方法名相同,参数列表相同,但返回值类型不同的方法时不能同时继承这两个接口
实现接口和继承抽象类相同,必须实现所有的抽象方法、
除非是抽象类,可以不实现所有的方法
接口和接口之间可以互相继承,并且可以继承多个
- 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.提供一个共有的获取对象的方法
- class Singleton {
- private Singelton() { //将构造函数私有化,其他类就无法通过构造函数创建对象
- }
- /*
- 由于构造函数私有化,因此无法同过new来创建对象
- 没有对象则无法调用类中的非静态方法,因此把方法声明为静态让类名直接调用返回一个对象
- */
- private static Singleton single = new Singleton();
- public static Singleton getInstance () {
- return single;
- }
- }
延迟加载的单例
普通的单例设计模式,在类加载的时候就会创建对象
而有的时候只是访问了类中的某个静态成员,而没有获取对象,这样创建就浪费了内存
所以我们可以使用类加载延迟的单例设计,成员变量处不直接创建对象,在第一次调用方法时创建
- class Singleton() {
- private static Singleton lazySingle = null;
- private Singleton() {
- }
- public static lazySingle getInstance() {
- if (lazySingle == null)
- lazySingle = new Singleton();
- return lazySingleton
- }
3.模版设计模式
在使用程序做一些事情的时候,如果每次都有一些步骤是重复的
那么就可以使用模版设计模式来精简,每次只写不同的地方
写法:
定义一个抽象类用作模版类
在其中定义一个final修饰的模版方法
在方法中把每次都一样的代码写上,每次不同的代码用抽象方法代替
使用的时候,定义类继承模版类,实现抽象方法,写上每次不同的代码
- 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();
- }
- }
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个
内部类
- 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();
- }
- }
匿名内部类
- 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培训、期待与您交流! ----------------------