前言:计划半个暑假之内系统学习一下JavaSE,现在已经学了一半左右,相信这个目标可以达成。由于本人有C语言的基础,故此笔记略去了基础内容,从Java的特性内容开始记录。开头篇为面向对象思想,内容跳跃性较大、详略不一,如有疑问可参考以下链接中的视频或参考相关书籍或使用搜索引擎等。
欢迎纠错。
教学视频百度云链接 密码:vij4
万物皆对象
Object类为所有其他类的父类,即上帝、老祖宗
三大特点
* 封装
* 继承
* 多态
隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
数据域的封装:将数据域使用private修饰为私有,并根据情况对外提供访问器(即get方法)和修改器(即set方法)
方法域的封装:对于一些内部使用且不希望向外暴露的方法也可以使用private修饰为私有
创建对象时调用的函数且一定会被调用
特点:
1. 函数名与类名相同
2. 没有具体的返回值
3. 无需定义返回值类型
作用:对创建的对象进行初始化
如果一个类没有定义任何的构造函数,那么该类中会有一个默认的空参数构造函数
代表当前对象的引用,就是对所在函数所属对象的引用。this也可以用于在构造函数中调用其他的构造函数,但只能定义在构造函数的第一条语句。
作用:修饰成员变量和成员函数
被修饰后成员(静态成员)具有以下特点:
* 随着类的加载而加载,随着类的消失而消失
* 优先于对象存在
* 被所有对象所共享,可用于同类对象间共享数据
* 可以直接被类名调用
注意:
* 静态方法只能调用静态成员
* 不可以使用this,super关键字
* main函数为静态函数
成员变量和静态变量的区别:
1. 生命周期不同
* 成员变量是对象所持有的,随着对象的创建而存在,随着对象的被回收而消失
* 静态变量则随着类的加载而存在,随着类的消失而消失
2. 调用方式不同
* 成员变量只能被对象调用。静态变量被对象和类名调用ClassName.staticVariables
3. 别名不同
* 成员变量也称为实例变量,静态变量称为类变量
4. 数据存储位置不同
* 成员变量数据存储在堆内存的实例对象当中,所有叫做对象的特有数据
* 静态变量数据存储与方法区的静态区,所以也叫做对象的共享数据
对于主函数main的分析:
主函数的格式是固定的,被JVM所识别调用
public static void main(String[] args)
public:权限必须最大
static:不需要对象,直接用主函数所属类名调用即可
main:固定的函数名
String[] args:main函数的参数列表,形参命名不固定
何时使用静态:
* 静态变量:在任何对象中数据都相同的变量则修饰为静态
* 静态函数:分析该函数功能是否有访问到对象中的特有数据,如果有则将该函数修饰为静态
随着类的加载而执行,并且只执行一次
作用:给类进行初始化
创建对象是调用,用于初始化对象
执行顺序:静态代码块>mian方法>构造代码块>构造方法
其中静态代码块只执行一次,构造代码块在每次创建对象是都会执行
作用:保证在一个JVM中,一个对象只有一个实例,并提供一个访问它的全局访问点。
应用:某些对象创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
优点:省去new操作符,可以降低系统内存的使用频率,减轻GC压力。
步骤:
1. 建立私有静态对象,防止被引用
2. 私有化构造方法,不让其他类建立该类对象(防止实例化)
3. 通过getInstance()对外提供对象
/**
* 懒汉式单例设计模式
* 特点:线程不安全,调用效率不高,可以延迟加载
* @classname Singleton1
* @author LiShengc
*/
public class Singleton1
{
// 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载
private static Singleton1 instance = null;
// 私有构造方法,防止被实例化
private Singleton1()
{
}
// 只有调用了getInstance()方法才会创建对象
public static Singleton1 getInstance()
{
if( instance == null )
instance = new Singleton1();
return instance;
}
}
/**
* 饿汉式单例设计模式
* @classname Singleton2
* @author LiShengc
*/
public class Singleton2
{
// 类被首次加载时,对象就已经被创建存在于内存中
private static Singleton2 instance = new Singleton2();
private Singleton2()
{
}
public static Singleton2 getInstance()
{
return instance;
}
}
优缺点比较:
饿汉式比懒汉式常用
1. 饿汉式在加载类时就加载了对象,懒汉式在加载类时对象为空,需要时加载。但是一般用到此方法是都是有对象的。
2. 懒汉式存在安全隐患,当多线程同时访问调用该类是会出现多个对象的可能,需要加入关键字synchronized(保证线程安全),但是加入此关键字会使程序调用变慢。
好处:
- 提高了代码的复用性
- 让类与类之间产生了关系,给多态提供了前提
java中只支持单继承(一个子类只能有一个直接父类),不直接支持多继承(因为多个父类中可能有相同成员,会产生调用不确定性),支持多层继承,但对C++中的多继承机制进行改良(引入接口)。
当需要使用一个继承体系时:
1. 查看该体系中的顶层父类,了解该体系的基本功能
2. 创建体系中的最子类对象,完成功能的使用
当子类的成员和局部变量同名时用this区分子类;当子父类中的成员变量同名时用super区分父类,this区分子类。
代表一个父类空间,与this的用法相似。在构造函数中只能在第一条语句中引用。
注意事项:
1. 子类方法覆盖父类方法是,子类权限必须要大于等于父类的权限
2. 静态方法只能覆盖父类的静态方法,或被其子类对应的静态方法覆盖
何时使用覆盖操作?
当需要对一个类进行子类的功能扩展时,子类需要保留父类的功能声明定义自身中该功能的特有内容时,就使用覆盖完成。
super();
,因此在子类构造对象时,访问子类构造函数时父类的构造函数也运行了,放在第一句是因为父类的初始化动作要优先完成。由于this和super构造语句都只能定义在第一行,因此同一个构造函数中只能调用一个。
Q&A
1.Q:抽象类中有构造函数吗?
A:有,用于给子类对象进行初始化。
2.Q:抽象类可以不定义抽象方法吗?
A:可以,但是很少使用,目的是为了不让该类实例化。
/**
* 抽象类、抽象函数声明示例
* @classname AbstractDemo
* @author LiShengc
*/
abstract class AbstractDemo{
//存在抽象函数,所以此类是抽象类,必须使用abstract修饰
void function1(){
//有方法体,非抽象函数
}
abstract void function2();//抽象函数,无方法体,必须使用abstract修饰
}
3.Q:abstract关键字不可以和哪些关键字共存?
A:private,final,static4.Q:抽象类一定是父类吗?
A: 是的,因为需要子类覆盖其方法后才可以对子类实例化进行使用。
5.Q:抽象类和一般类的异同点?
A:相同点:都是用来描述事物,都在内部定义了成员
不同点:
* 一般类具有足够的信息描述事物,抽象类描述事物的信息有可能不足
* 一般类中不可定义抽象方法,只能定义非抽象方法;抽象类中可定义抽象方法和非抽象方法
* 一般类可被实例化,抽象类不能被实例化
若一个子类同时实现存在同名同形参的多个接口成员函数情况下,编译时将会报错,不允许此情况发生,必须避免。在可操作的情况下可以改为接口之间的继承,然后子类对其进行实现。
抽象类与接口的异同点
相同点:都是不断向上抽取而来的
不同点:
1. 抽象类需要被继承,而且只能单继承;
接口需要被实现,可以多实现
2. 抽象类中可以定义非抽象方法,子类继承后可以直接对非抽象方法进行使用;
接口中只能定义抽象方法,必须由子类全部实现,否则该类是抽象类不可被实例化。
3. 抽象类的继承是is a关系,在定义上共享该体系的基本共性内容;
接口的实现是like a关系,用于定义体系的额外功能。
// 两个子类Student和Worker都继承了Person类
// Student类对父类show方法进行了覆盖;Worker类没有覆盖show方法,但实现了特有方法work。
class Person{
private String name;// 私有化数据域
private int age;
public Person( String name, int age ){
this.name = name;
if( age > 0 && age < 120 )// 对输入的数据进行筛选
this.age = age;
else
this.age = 1;
}
public void show(){
System.out.println( name + ":" + age + " " + Person.show()" );
}
// 访问器
public String getName(){
return name;
}
// 修改器
public void setName( String name ){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge( int age ){
this.age = age;
}
}
/**
* 继承Person并覆盖父类的show()方法
* @classname Student
* @author LiShengc
*/
class Student extends Person{
public Student( String name, int age ){
super( name, age );// 引用父类的构造函数
}
public void show(){
System.out.println( "studying..." );
}
}
/**
* 继承Person又拥有特有内容(方法work())
* @classname Worker
* @author LiShengc
*/
class Worker extends Person{
public Worker( String name, int age ){
super( name, age );
}
public void work(){
System.out.println( name + ":" + age + " " + "working..." );
}
}
/*
* 主函数
*/
public class Test{
public static void main( String[] args ){
Person person1 = new Student( "小强", 15 );// 向上转型
Person person2 = new Worker( "大强", 40 );
function( person1 );
function( person2 );
}
public static void function( Person person ){
person.show();// 如果子类中覆盖了父类方法,则调用子类方法
if( person instanceof Student ){// 健壮性判断
Student student = (Student)person;// 向下转型
student.show();
}
if( person instanceof Worker ){
Worker worker = (Worker)person;
worker.work();// 调用子类特有方法
}
}
}
输出结果:
studying...
studying...
Person.show()
working...
多态的特点: * 成员函数: 编译时:查看引用变量所属的类中是否有所调用成员 运行时:查看对象所属的类中是否有所调用成员 简单来说,编译看左边,运行看右边。 * 成员变量: 只看引用变量所属的类。简单来说,参考等号左边。 * 静态函数: 无需对象,直接用类名调用即可。
包名.类名
访问权限 | public | protected | (default) | private |
---|---|---|---|---|
同一类中 | ok | ok | ok | ok |
同一包中 | ok | ok | ok | x |
子类中 | ok | ok | x | x |
不同包中 | ok | × | x | x |
2016/8/21 星期日 上午 by LiShengc