------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
面向对象:
特点:1:将复杂的事情简单化。
2:面向对象将以前的过程中的执行者,变成了指挥者。
3:面向对象这种思想是符合现在人们思考习惯的一种思想。
类和对象的关系
类就是:对现实生活中事物的描述。
对象:就是这类事物,实实在在存在个体。
属性对应是类中变量,行为对应的类中的函数(方法)。
其实定义类,就是在描述事物,就是在定义属性和行为。属性和行为共同成为类中的成员(成员变量和成员方法)。
在类中定义其实都称之为成员。成员有两种:
1:成员变量:其实对应的就是事物的属性。
2:成员函数:其实对应的就是事物的行为。
成员变量和局部变量的区别:
1:成员变量直接定义在类中。
局部变量定义在方法中,参数上,语句中。
2:成员变量在这个类中有效。
局部变量只在自己所属的大括号内有效,大括号结束,局部变量失去作用域。
3:成员变量存在于堆内存中,随着对象的产生而存在,消失而消失。
局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放
匿名对象。
匿名对象使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。如果对一个对象进行多个成员调用,必须给这个对象起个名字。
匿名对象使用方式二:可以将匿名对象作为实际参数进行传递。
书写格式例如:new Student().toString();
面向对象:三个特征:封装,继承,多态。
封装:
封装是指隐藏对象的属性和实现细节,仅对外提供公共的访问方式。
好处: 1将变化隔离 2便于使用3 提高重用性4提高安全性
private int age;//私有的访问权限最低,只有在本类中的访问有效。
注意:私有仅仅是封装的一种体现形式而已。
私有的成员:其他类不能直接创建对象访问,所以只有通过本类对外提供具体的访问方式来完成对私有的访问,可以通过对外提供函数的形式对其进行访问。
好处:可以在函数中加入逻辑判断等操作,对数据进行判断等操作。
总结:开发时,记住,属性是用于存储数据的,直接被访问,容易出现安全隐患,所以,类中的属性通常被私有化,并对外提供公共的访问方法。
这个方法一般有两个,规范写法:对于属性 xxx,可以使用setXXX(),getXXX()对其进行操作。
构造函数:
构造函数函数名和类名相同。2不用定义返回值类型。3不可以写ruturn语句。
构造函数的作用:可以用于给对象进行初始化。
因此所有对象创建时,都需要初始化才可以使用。
构造函数和一般函数有什么区别呢?
1:两个函数定义格式不同。
2:构造函数是在对象创建时,就被调用,用于初始化,而且初始化动作只执行一次。
一般函数,是对象创建后,需要调用才执行,可以被调用多次。
分析事物时,发现具体事物一出现,就具备了一些特征,那就将这些特征定义到构造函数内。
构造代码块
给对象进行初始化。对象一建立就运行,而且优先于构造函数运行。
构造代码块和构造函数的区别:
构造代码块是给所有对象进行统一初始化,
而构造函数是给对应的对象初始化。
this:代表对象。就是所在函数所属对象的引用。
this到底代表什么呢?
哪个对象调用了this所在的函数,this就代表哪个对象,就是哪个对象的引用。
开发时,什么时候使用this呢?
在定义功能时,如果该功能内部使用到了调用该功能的对象,这时就用this来表示这个对象。
this还可以用于构造函数间的调用。
调用格式:this(实际参数);
this对象后面跟上 . 调用的是成员属性和成员方法(一般方法);
this对象后面跟上 ()调用的是本类中的对应参数的构造函数。
注意:用this调用构造函数,必须定义在构造函数的第一行。因为构造函数是用于初始化的,所以初始化动作一定要执行。否则编译失败。
package pract;
public class Student {
private String name;//成员变量
private int age;//private 私有权限修饰,需要对外提供公共的访问方法。
{//构造代码块:用于给所有对象初始化
System.out.println("学习");
}
public Student() {
super();
}
public Student(String name, int age) {//构造函数,给对应对象初始化
this();// 调用的是本类中的对应参数的构造函数。
this.name = name;//this用于构造函数内,调用的是成员属性name;
this.age = age;
}
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;
}
public String toString() {//返回值为String的一个方法;此方法是返回对象的姓名年龄。
return "Student [name=" + name + ", age=" + age + "]";
}
public static void main(String[] args) {
Student s = new Student("liming",12);//名字为s的学生类对象
System.out.println(s.toString());
System.out.println(new Student("zhangsan",22).toString());//匿名对象
}
/*程序输出结果如下:
* 学习
*Student [name=liming, age=12]
*学习
*Student [name=zhangsan, age=22]
*
* */
}
static
特点:
1,想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
2,被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
3,静态随着类的加载而加载。而且优先于对象存在。
弊端:
1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2,静态方法只能访问静态成员,不可以访问非静态成员。
因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3,静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。
4,主函数是静态的。
什么时候定义静态成员呢?或者说:定义成员时,到底需不需要被静态修饰呢?
成员分两种:
1,成员变量。(数据共享时静态化)
该成员变量的数据是否是所有对象都一样:
如果是,那么该变量需要被静态修饰,因为是共享的数据。
如果不是,那么就说这是对象的特有数据,要存储到对象中。
2,成员函数。(方法中没有调用特有数据时就定义成静态)
如果判断成员函数是否需要被静态修饰呢?
只要参考,该函数内是否访问了对象中的特有数据:
如果有访问特有数据,那方法不能被静态修饰。
如果没有访问过特有数据,那么这个方法需要被静态修饰。
成员变量和静态变量的区别:
1,成员变量所属于对象。所以也称为实例变量。
静态变量所属于类。所以也称为类变量。
2,成员变量存在于堆内存中。
静态变量存在于方法区中。
3,成员变量随着对象创建而存在。随着对象被回收而消失。
静态变量随着类的加载而存在。随着类的消失而消失。
4,成员变量只能被对象所调用 。
静态变量可以被对象调用,也可以被类名调用。
所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
静态的注意:静态的生命周期很长。
静态代码块:就是一个有静态关键字标示的一个代码块区域。定义在类中。
作用:可以完成类的初始化。静态代码块随着类的加载而执行,而且只执行一次(new多个对象就只执行一次)。如果和主函数在同一类中,优先于主函数执行。
Public:访问权限最大。
static:不需要对象,直接类名即可。
void:主函数没有返回值。
Main:主函数特定的名称。
(String[]args):主函数的参数,是一个字符串数组类型的参数,jvm调用main方法时,传递的实际参数是 new String[0]。
jvm默认传递的是长度为0的字符串数组,我们在运行该类时,也可以指定具体的参数进行传递。可以在控制台,运行该类时,在后面加入参数。参数之间通过空格隔开。jvm会自动将这些字符串参数作为args数组中的元素,进行存储。
package pract;
class StaticCode{
final static int num = 9;//静态变量也是类变量
static{//静态代码块
System.out.println("a");
}
StaticCode(){//无参数构造函数
System.out.println("b");
}
{//构造代码块
System.out.println("c"+num);//调用静态不用this
}
StaticCode(int x){//有参数构造函数
System.out.println("d");
}
public static void show(){//show方法
System.out.println("show run");
}
}
public class StaticCodeDemo {
static{//staticCodeDemo的静态代码块
System.out.println("e");
}
public static void main(String[] args) {
new StaticCode();// e a c9 b ;
new StaticCode(4);//e a c9 d;
//静态代码块、构造代码块、构造函数同时存在时的执行顺序:静态代码块 ,构造代码块 , 构造函数;
}
}
单例设计模式保证一个类在内存中的对象唯一性。
package pract;
public class SJMS {
/*如何保证对象唯一性呢?
思路:
1,不让其他程序创建该类对象。
2,在本类中创建一个本类对象。
3,对外提供方法,让其他程序获取这个对象。
步骤:
1,因为创建对象都需要构造函数初始化,只要将本类中的构造函数私有化,其他程序就无法再创建该类对象;
2,就在类中创建一个本类的对象;
3,定义一个方法,返回该对象,让其他程序可以通过方法就得到本类对象。(作用:可控)
*/
// 恶汉式
private SJMS(){}
private static SJMS sjms = new SJMS();
public static SJMS getInstance(){
return sjms;
}
}
class SJMS2{
private SJMS2(){}//懒汉式
private static SJMS2 sjms2 = null;
public static SJMS2 getInstance(){
if(sjms2==null){
sjms2 = new SJMS2();
}
return sjms2;
}
}
继承特点:
1,提高了代码的复用性。
2,让类与类之间产生了关系。有了这个关系,才有了多态的特性。
Java语言中:java只支持单继承,不支持多继承。
1,因为多继承容易带来安全隐患:当多个父类中定义了相同功能,当功能内 容不同时,子类对象不确定要运行哪一个。
2,但是java保留这种机制。并用另一种体现形式来完成表示。多实现。
,3,ava支持多层继承。也就是一个继承体系(爷爷父亲子)。
如何使用一个继承体系中的功能?
想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能。通过了解共性功能,就可以知道该体系的基本功能。
那么在具体调用时,要创建最子类的对象,为什么呢?
1,是因为有可能父类不能创建对象,
,2,是创建子类对象可以使用更多的功 能,包括基本的也包括特有的。
如果子类中出现非私有的同名成员变量时,
1,子类要访问本类中的变量,用this,this代表的是本类对象的引用。
, 2子类要访问父类中的同名变量,用super。super代表的是父类对象的引用。
当子类出现和父类一模一样的函数时,会发生覆盖。
1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否 则编译失败。
2,静态只能覆盖静态。
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。
super调用一般函数是super.方法,调用构造函数是super()
当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。
当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
final最终是一个修饰符
1,可以修饰类,函数,变量。
2,被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
3,被final修饰的方法不可以被复写。
4,被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,有可以修饰局部变量。
5作为常量:常量的书写规范所有字母都大写,如果由多个单词组成。单词间通过_连接。
package pract;
class Fu{
public static final double PI = 3.14;
public Fu() {
super();//这是调用Object的构造函数,因为Object是所有class的父类
System.out.println("这是Fu类"+PI);
}
public void show(){
System.out.println("这是父类的show方法");
}
}
class Zi extends Fu{
public Zi() {
super();
// super() 调用Fu类的构造函数
System.out.println("这是zi类"+PI);//调用父类的PI
}
public void show(){ //覆盖父类中的show方法
System.out.println("这是子类的show方法");
}
}
public class ExtendsDemo {
public static void main(String[] args) {
new Zi().show();//匿名对象
/*程序运行结果如下:
这是Fu类3.14
这是zi类3.14
这是子类的show方法
*/
}
}
抽象类:abstract
在不断抽取过程中,将共性内容中的方法声明抽取,但是方法不一样,没有抽取,这时抽取到的方法,并不具体,需要被指定关键字abstract所标示,声明为抽象方法。
抽象方法所在类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。
抽象类的特点:
1,抽象方法一定在抽象类中。
2,抽象方法和抽象类都必须被abstract关键字修饰。
3,抽象类不可以用new创建对象。因为调用抽象方法没意义。
4,抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
抽象类的细节:
1:抽象类中是否有构造函数?有,用于给子类对象进行初始化。
2:抽象类中是否可以定义非抽象方法?
可以。抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
3:抽象关键字abstract和哪些不可以共存?final , private , static
4:抽象类中可不可以不定义抽象方法?可以。抽象方法目的仅仅为了不让该类创建对象。
abstract class Student//一个抽象的Student类
{
abstract final void study();//抽象的study方法,需要被子类实现。
void sleep()//抽象类中可以定义非抽象方法。
{
System.out.println("躺着");
}
}
模板方法设计模式
/*
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减即可。
获取时间:System.currentTimeMillis();
*/
abstract class GetTime
{
public final void getTime()
{
long start = System.currentTimeMillis();//程序开始的时间
runcode();//这个模式是模板方法设计模式
/*
什么是模版方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,
那么这时就将不确定的部分暴露出去。由该类的子类去完成。
*/
long end = System.currentTimeMillis();//程序结束的时间
System.out.println("毫秒:"+(end-start));//计算出程序运行的时间
}
public abstract void runcode();//模板方法,吧不确定的程序暴露出去
}
class SubTime extends GetTime
{
public void runcode()//继承GetTime类,实现不确定的程序
{
for(int x=0; x<4000; x++)
{
System.out.print(x);
}
}
}
public class TemplateDemo
{
public static void main(String[] args)
{
SubTime gt = new SubTime();//建立子类对象
gt.getTime();//获取程序运行时间
}
}
interface用于定义接口
1,接口中常见定义:常量,抽象方法。
2,接口中的成员都有固定修饰符。
常量:publicstatic final
方法:publicabstract
3:接口中有抽象方法,说明接口不可以实例化。接口的子类必须实现了接口中所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
4:类与类之间存在着继承关系,类与接口中间存在的是实现关系。
继承用extends ;实现用implements;
5:接口和类不一样的地方,就是,接口可以被多实现,这就是多继承改良后的结果。
class Test extends Demo implements Inter,InterA
6:一个类在继承另一个类的同时,还可以实现多个接口。所以接口的出现避免了单继承的局限性。还可以将类进行功能的扩展。
7:其实java中是有多继承的。接口与接口之间存在着继承关系,接口可以多继承接口。
接口都用于设计上,设计上的特点:(可以理解主板上提供的接口)
1:接口是对外提供的规则。
2:接口是功能的扩展。
3:接口的出现降低了耦合性。
抽象类与接口:
抽象类:一般用于描述一个体系单元,将一组共性内容进行抽取,特点:可以在类中定义抽象内容让子类实现,可以定义非抽象内容让子类直接使用。它里面定义的都是一些体系中的基本内容。
接口:一般用于定义对象的扩展功能,是在继承之外还需这个对象具备的一些功能。
抽象类和接口的共性:都是不断向上抽取的结果。
抽象类和接口的区别:
1:抽象类只能被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
2:抽象类中可以定义非抽象方法,子类可以直接继承使用。
接口中都有抽象方法,需要子类去实现。
3:抽象类使用的是 is a关系。
接口使用的 like a关系。
4:抽象类的成员修饰符可以自定义。
接口中的成员修饰符是固定的。全都是public的。
package pract;
abstract class animal{//抽象类
abstract void eat();
abstract void sleep();
}
interface living//接口
{
void live();
}
public class Dog extends animal implements living {
public void eat(){//覆盖abstract 类 的eat方法
System.out.println("吃骨头");
}
public void sleep(){//覆盖abstract类的sleep方法
System.out.println("趴着睡");
}
public void live(){//实现接口的live方法
System.out.println("生活在陆地上");
}
public static void main(String[] args) {
// 创建Dog对象,调用Dog方法
Dog d = new Dog();
d.eat();
d.sleep();
d.live();
}
}