黑马程序员—4、JAVA基础&面向对象
--------------------- android培训、 java培训、期待与您交流! ----------------------
面向对象的特点:
1 、 面向对象就是更符合人们思考习惯的一种思想。
2 、 从面向过程的执行者,转换成面向对象的指挥者
3 、 面向对象将复杂的事情简单化。
OOP面向对象程序 OOA面向对象分析 OOD面向对象设计
在写程序的时候没有对象,那么就需要我们自己造对象,其实就建立一个对象供我们以后使用。
类与对象之间的关系:
1、类:是对具体事物的描述,描述中包含了该类事物所具备的共性内容。
2、对象:就是该类事物现实中实实在在存在的个体(对象)。
通过java的class来产生一个计算机内存的实体。
那么是先有类还是先有对象呢?这要看怎么理解了,当我们在做一个项目的时候,需要对现实生活中的事物进行分析,这个我们看到的已经是对象了,那么这个时候用计算机描述的话就是类,在通过new关键在计算机中产生的又叫对象。两者有什么差别呢,一个现实生活中的对象,一个是计算机内存中的对象。
/* 用java语言来描述一个小汽车
描述事物:无非就是描述的属性和行为
属性:轮胎数,颜色
行为:运行。
用java描述是通过类的形式来体现的
在类中定义的变量和函数都称为类中的成员:
成员: 成员变量----属性
成员函数----行为(方法)
*/
class Car
{
int num; // 定义在类中的变量(事物的属性)
String color; // 定义在类中的变量(事物的属性)
void run() // 定义在类中的函数(事物的行为)
{
System.out.println(num+"......"+color);
}
}
class CarDemo
{
public static void main(String[] args)
{
//通过Car类的描述,在内存中创建该类的实体(对象),要使用new关键字开辟空间
Car c = new Car();// 创建了一个Car类事物的对象。
// c是一个类类型的变量,注意,类类型的变量一定指向对象。
// 指挥对象做事情:对象.对象成员 这是使用对象内容的调用方式
c.num = 4;
c.color = "red";
c.run();
show(new Car);
}
public static void show(Car c)
{
c.num = 3;
c.color = "black"
}
}
当一个对象在内存已生成的话,并不是根据我们写的那个类(其实是原文件代码)来生成一个对象的,根据的是当我们编译这个类的时候会生成一个class 文件,当我们这个class文件生成后,就算我们把源文件删除也无所谓,计算机把这个class文件加载进内存,根据这个class文件中的内容来创建对象的。这个时候这个对象就在堆内存中产生了,并且对象的变量也在堆内存中,堆内存中的变量有个特点,会自动初始化。然后会把这个对象在堆内存中的地址赋给对象的引用变量。当赋值结束后,那么对象的产生就结束了。
原来对象本身就是一个容器,对象就是可以存储更多不同数据类型的容器;存储的都是每一个对象特有的数据,对所属自己的数据进行封装
当我们需要多个对象的时候做同一件事情的时候,发现这些代码重复很多,复用性很差,所以我们这个时候可以创建一个功能,然后建立不同的对象去调用这个功能。这个时候又发现,每一个对象只调用一次这个功能,因此就想着能不能进行简化呢,于是就产生了匿名对象。
class Car
{
int num;
String color;
void run()
{
System.out.println(num+"....."+color);
}
}
class CarDemo
{
public static void main(String[] args)
{
Car c1 = new Car();
Car c2 = new Car();
c1.num = 4;
c1.color = "red";
c1.run();
c2.num = 4;
c2.color = "red";
c2.run();
}
public static void show(Car c)
{
c.num = 3;
c.color = "black";
c.run();
}
}
匿名对象:没有名字的对象,简化书写 Car c = new Car();该对象名称为c。
new Car();此时就是一个匿名对象,这个对象在堆内存已经产生,但是没有实际引用名。
匿名对象的基本使用:
1、可以作为实际参数进行函数的参数传递;
2、当对象的方法只进行一次调用时,可以使用匿名对象进行简化
Car c = new Car();
c.run(); 此时就可以采用匿名对象来代替上面这两句话 new Car().run;
记住了,一旦对对象进行多个成员操作时,必须给对象起名字。但匿名对象也有一个弊端,对象已建立就变成了垃圾,无法再使用。
无法再使用。
成员变量和局部变量的区别:
1、源代码定义位置不同
成员变量:定义在类中,在整个类中有效。
局部变量:定义在函数中,在局部范围内有效。
2、在内存中的出现时间和出现位置都不同(生命周期不同)。
成员变量:随着对象的创建而出现在堆内存中。随着对象被回收而消失。
局部变量:随着变量所属局部区域的运行,而出现在栈内存中,随着所属区域的运行结束而释放。
3、变量使用的初始化:
成员变量:因为在堆内存中,都有默认的初始化值,对于应用型变量默认值为null
局部变量:因为在栈内存中,都没有默认初始化值,必须手动初始化后才可以使用。
面向对象的三个特征:
1、封装
2、继承
3、多态:
封装:凡是面向对象必须有封装性。封装隐藏实现细节,对外提供公共的访问方式。
封装的特点:
1、易于使用。2、提高安全性。3、隔开了变化。4、提高了复用性。
举例:机箱就是一个封装性的体现。在代码中的体现:函数就是一个最小的封装体。
封装性在代码中的体现:
1、将成员变量都私有化,并通过公有的方法对其进行访问。这个两个公有方法是: setXxx getXxx
2、只不要准备对外提供的,全都封装起来。记住:私有仅仅是封装一种体现形式而已。封装并不等于私有,私有只是封装的一种体现。当我们将成员变量私有了,对外提供公共的访问方法,这个时候当我们给这个方法传值的时候,首先对这个值进行判断,这样我们可以对类中的数据进行可控(其实就是健壮性的判断)。以防止错误数据的传入。
class Person
{
private int age; //为了不让其他程序直接访问age属性,避免错误数据,可以降低成员的访问权限。
// 可以使用一个关键字private 私有, 它是一个权限修饰符,只能修饰成员(成员变量和成员函数)。
// 私有只在本类中的访问有效。
void speak()
{
System.out.println("age="+age);
}
public void setAge( int a )
{
if( age > 130 || age < 0 )
System.out.println("数据非法");
else age = a ;
}
}
class PersonTest
{
public static void main(String[] args)
{
Person p = new Person();
p.age = 21; //不能直接访问了
p.setage(23);
}
}
构造函数的作用?
每创建一个对象都会执行这个构造动作,所以构造函数的作用是给对象进行初始化的。
this关键字有什么含义?在哪些情况下应用?
Java中为了解决变量的命名冲突和不确定性问题,引入了关键字this。this代表的是当前类的一个引用,它经常出现在函数和构造函数。
1, 返回调用当前函数的对象的引用。
2, 在构造函数中调用当前类中的其他构造函数。
3, 当方法参数名和成员变量名相同时,用于区分参数名和成员变量名。
static关键字具体如何应用?能修饰构造函数?
1,它是一个修饰符,只能修饰成员(成员变量和成员函数)。
2,被static修饰的成员变量的数据,可以被对象们所共享。
3,被静态修饰的成员多了一种调用方式,除了被对象调用以外,还可以被类名直接调用。格式:类名.类名成员。
4,静态之所以可以被类名调用,那是因为,静态成员是随着类的加载而加载进内存的。(非静态的成员是随着对象的加载而加载进内存)。
注意:static不能修饰构造函数。
静态代码块:
class Demo
{
{
} 类代码块或者构造代码块
static静态代码块
{
}
void show()
{
{
} 局部代码块
}
}
构造代码块随着对象的加载而运行,是给所有对象进行初始化的。
静态的(包含静态代码块和静态成员变量、静态函数)都是随着类的加载而加载的,而对于静态中的成员变量和函数,也是随着类的加载,只不过需要类名调用才能够运行。而对于静态代码块没有名,没有办法通过名称调用,那么静态代码块在类一加载的时候就执行。随着类的加载而执行,而且只执行一次,一旦加载进内存后不在执行,除非类被重新加载。静态代码块一般用于给类进行初始化。
先加载静态代码块-->>类代码块-->>构造函数
当某一个类中的所有成员变量和函数全部静态的话,此时不需要创建本类对象就可以通过类名直接调用本类中的所有成员变量和函数。这个时候就需要将本类中的构造函数私有化,不让其他类创建本来对象。因为创建本来对象没有用,不需要本类对象就可以访问本类中的所有变量和函数。但是类中还想有一些初始化的动作(因为此时构造函数私有了,就无法创建本类对象,同时构造代码块也无法加载),那么此时应该用静态代码块来完成。静态的初始化动作是最先执行的,类一加载这个动作就结束了,至于类需不需要对象,我根本不知道,反正先把类初始化完毕。初始化类的目的其实是为了初始化类中的某些静态数据或者某些静态的行为。但是静态有局限性,所以要注意静态中无法给非静态初始化。
注意面试题:
class Test
{
static int num = 4;
{
num+=3;
}
Test()
{
}static
{
}
}
new Test(); 请写出这个程序的执行顺序。这个时候就需要明白new 的时候都干了什么。
类一加载先执行静态代码块,然后构造代码块,接下来是构造函数,一定要记清楚内存中他们的执行顺序。
默认的构造函数和类的权限一致。
文档注释:
凡是public的方法都需要写文档注释。
/**
文字说明自己当前这个功能的具体用法和参数等
@author 作者
@version 版本号
*/
实例:
/**
ArrayTool是用于操作数组的工具类,其中定义了常见的操作数组的功能。比如获取最值等。
@author 李四
@version V1.0
*/
public class ArrayTool
{
/**
这是一个空参数构造器。
*/
private ArrayTool(){}
/**
获取整数数组中的最大值。
@param arr 接收一个元素是int类型的数组。
@return 返回这个数组的最大的元素。
*/
public static int getMax(int[] arr)
{
int index = 0;
for(int x=1; x<arr.length; x++)
{
if(arr[x]>arr[index])
index = x;
}
return arr[index];
}
/**
选择排个序
@param arr 接收一个数组哦也。
*/
public static void selectSort(int[] arr)
{
for(int x=0; x<arr.length-1; x++)
{
for(int y=x+1; y<arr.length; y++)
{
if(arr[x]>arr[y])
swap(arr,x,y);
}
}
}
/*
对数组中的元素进行位置的置换
//@param arr 接收一个数组哦哦哦哦哦。
*/
private static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
运行的时候可以对我们的源代码中的文档和注释进行提取的时候会形成文档,这个文档不是一个文件,是由多个文件所组成的一个网页文档。那么就意味文件一多的话,我们就需要一个文件存放的位置。这个时候我就需要一个-d来指定文档存放的位置。例如: javadoc –d myhelp -version -author 文件名.java 当输入完后就会自动在指定的位置生成一个文档。注意被文档化的类,这个类必须用public来修饰。
当我们想使用别人写好的java程序,这个时候只要将它的文档路径给我们的classpath中一配置,我们就可以用了。然后我们打开这个应用程序的说明文档,就可以去应用这个程序了。
当我们编译一个文件的时候,如果中用到了不在文件中的其他类,那么这个时候编译器会在当前目录中先对应的类文件,如果没有找到,然后会在当前目录找有没有对应的类名的源文件。如果还没有找到就会编译失败。
设计模式:设计模式来源某一建筑行业,在日常工作总结的一些有效的结局问题的办法。后人在使用的就可以参照这个办法来解决问题。解决问题行之有效的解决思想。面向对象语言共有23种设计模式(是一种思想)。这23种是最基础最核心的思想,它们可以分化出更多的问题出来。以后开发中我们不一定会接触到所有设计模式,需要根据具体问题具体分析。
单例设计模式:保证一个类在内存中的对象唯一性。
思路:
1、为了防止其他程序建立指定类的对象,可以不让其他程序创建该类对象。将本类的构造函数私有化。
2、在本类中自定义本类对象。
3、对外提供一个可以访问本类对象的访问方式
步骤:
1、将构造函数私有化。
2、用new在本类中创建一个本类对象。
3、对外提供一个方法返回该类对象。
class Single // 饿汉式
{
private static Single s = new Single(); 必须私有
private Single(){}
public static Single getInstance() 对外提供方法的目的就是让数据可控
{
return s;
}
}
class Single2 // 延迟加载方式 懒汉式 因为多线程技术存在并发访问会造成懒汉式不安全
{
private static Single2 s = null;
private Single2(){}
public static Single2 getInstance()
{
if( s==null )
s = new Single2();
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single a = Single.getInstance(); 类名直接调用
}
}
单例设计模式什么时候应用,就是当要保证对象唯一的时候就可以使用单例设计模式。
单例的简单应用:
class Person
{
private int age;
private static Person p = new Person(5);
private Person(int age)
{
this.age = age;
}
public static Person getInstance() 获取对象的实例
{
return p;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
}
class SingleDemo
{
public static void main(String[] args)
{
// Person p1 = new Person(34); 无法创建Person对象
// Person p2 = new Person(56); 无法创建Person对象
Person p1 = Person.getInstance();
Person p2 = Person.getInstance();
p1.setAge(40);
p2.setAge(50);
System.out.println(p1.getAge());
System.out.println(p2.getAge());
}
}
饿汉式是在类在加载的时候对象就产生了,而懒汉式只有被调用的时候才产生对象,否则不会产生对象。
在开发的时候一般用饿汉式。懒汉式有线程不安全性。
--------------------- android培训、java培训、期待与您交流! ----------------------
详细请查看: http://edu.csdn.net/heima