黑马程序员_Java面向对象上

------- android培训java培训java博客、java学习型技术博客、期待与您交流! ----------


面向对象

1.1、理解面向对象:
         面向对象是相对过程而言,面向对象和面向过程都是一种思想,面向过程强调的是功能行为,面向对象将功能封装进对象,强调具备了功能的对象。面向对象是基于面向过程的。
面向对象的特点:
是一中思想,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者。
完成需求时:
 先要去找具有所需功能的对象来用;如果该对象不存在,那么创建一个具有所需功能的对象;
这样简化开发并提高复用性。
面向对象的三大特性:封装、继承、多态
成员变量与局部变量区别:
  作用范围:
   1、成员变量作用在整个类中。
   2、局部变量作用于函数中或者语句中。
  在内存中的位置:
   1、成员变量:在堆内存中,因为对象的存在,才在内存中存在。
   2、局部变量:存在栈内存中
  默认初始化值:
   1、局部变量没有默认初始化值。
   2、成员变量有默认初始化值
1.2、匿名对象
 匿名对象是对象的简化形式
 匿名对象两种使用情况
一、 当对对象方法仅进行一次调用时;
二、匿名对象可以作为实际参数进行传递
例、new Car() . num=5;
new Car() . color=”blue”;
如果对一个对象进行多个成员调用,必须给这个对象起个名字。
Car c=new Car();
   c.num=5 ;
   c.color=”blue” ;
1.3、封装(Encapasulation)
① 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
② 好处:将变化隔离
          便于使用
          提高复用性
          提供安全性
③ 封装原则:
将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共方法对其访问。
private:私有,权限修饰符,用于修饰类中的成员(成员变量、成员函数);私有只在本类中有效。
/*将age私有化后,类以外即使建立了对象也不能直接访问。
 * 但是人应该有年龄,就需要在Person类中提供对应访问age的方式。setxxx()与getxxx().
 *注意:私有仅仅是封装的一种体现形式,但并不能说私有是封装。 
 *
 *之所以对外提供访问方式,就是因为可以在访问方式中加入逻辑判断等语句。
 *对访问的数据进行操作。提高代码健壮性。
 * */
class Person{
private int age;
public void setAge(int a){
if(a>0&&a<130){
 age=a;
 speak();
}
else
System.out.println("非法年龄");
}
public int getAge(){
return age;
}
void speak(){
System.out.println("age="+age);
}
}
public class PersonDemo {
public static void main(String[] args) {
        Person p=new Person();
        //p.age=-20;访问不到的
        p.setAge(33);
}
}
1.4、构造函数:
特点:
1. 函数名与类名相同
2. 不用定义返回值类型
3. 不可以写return语句
对象一建立就会调用对应的构造函数;例如:new Person();(调用无参构造方法)
作用:给对象进行初始化。
注意:
 1. 默认构造函数的特点
 2.多个构造函数是以重载的形式存在的。
    他们之间参数类型不同或参数顺序不同或和参数个数不同形成了重载。
构造函数小细节:
当一个类中没有定义构造函数时,那么系统就会默认给该类加入一个空参数的构造函数。
当类中自定义了构造函数后,默认的构造函数就没有了。
class Person{
  Person(){} //构造函数
}
class PersonDemo{
  Public static void main(String[] args){
   New Person();
 }
}
构造函数和一般函数不同点:
构造函数和一般函数在写法上有不同。在运行上也有不同,构造函数是在对象一建立就运行,给对象初始化。而一般方法是对象调用才执行,给对象添加对象具备的功能。一个对象一建立,构造函数只运行一次。而一般方法可以被该对象 调用多次。
构造代码块
作用:给对象进行初始化。
对象一建立就运行,而且优先于构造函数执行。
和构造函数区别:
  构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化。
构造代码块中定义的是不同对象共性的初始化内容。
class Person1{
private String name;
Person1(){
System.out.println("name="+name);
}
Person1(String name){
this.name=name;
System.out.println("name="+name);
}
{
System.out.println("我是构造代码块,一出生就会哭");
}
}
public class Test {
public static void main(String[] args) {
//调用对应构造函数
new Person1();
        new Person1("king");
}
}
构造函数私有化:
如果所有的构造函数都私有化后,则说明这个类是不能创建对象的。
1.5this关键字
     this: 是用于区分局部变量和成员变量的同名情况。
     this为什么可以解决这个问题,?到底代表?
     this就是代表本类的对象,到底代表哪一个呢?
     this代表他所在函数所属对象的引用。
     简单的说:哪个对象在调用this所在的函数,this就代表哪个对象。
例如:
class Person2{
private String name;
Person2(String name){
           this.name=name;
          //此时this就代表p,因为p的所属对象new Person2("wangtao")调用了此构造函数
}
public void speak(){
 System.out.println("姓名:"+this.name);//此处this可以省略,写上阅读性更强,                       表示p对象的name 
}
 }
public class TestPerson {
public static void main(String[] args) {
Person2 p=new Person2("wangtao");
p.speak();
}
}
This的应用2:当定义类中功能(函数)时,该函数内部要用到该函数的对象时,这是用this来表示这个对象。
            但凡本类功能内部使用到了本类对象,都用this表示。
class Person2{
private int age;
Person2(int age){
this.age=age;//
}
//需求:给人定义一个用于比较年龄是否相同的功能。判断是否是同龄人。
public boolean compare(Person2 p){
return this.age==p.age;
//p1的对象调用了此函数,this代表p1;参数是p2所以p代p2
//此时就可以比较p1的年龄和P2的年龄是否相同了
}
}
public class TestPerson {
public static void main(String[] args) {
Person2 p1=new Person2(23);
Person2 p2=new Person2(24);
boolean b=p1.compare(p2);
System.out.println(b);
}
}
this关键字在构造函数间的调用
  this语句:用于构造函数之间的调用,this语句只能定义在构造函数的第一行,因为初始化要先执行。
 在普通函数中用this调用函数是不好使的。
例:class Person3{
private String name;
private int age;
Person3(String name){
this.name=name;
}
Person3(String name,int age){
this(name);//调用上面函数
this.age=age;
}
}
6.1、静态:static
   用法:是一个修饰符,用于修饰成员(成员变量,成员函数);
   静态修饰的变量被对象所共享。
   当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可以直接被类名调用。
   格式是:类名.静态成员
   特有内容随着对象存储,比如人的name是每个人特有的,不必共享。
String  name;  非静态变量(成员变量,实例变量)
static  String  country=”CN”;  //静态变量(静态的成员变量,类变量)
 statict特点:
一、随着类的加载而加载(随着类的消失而消失)
    也就是说它的生命周期最长
二、优先于对象存在
         明确一点:静态是先存在,对象是后存在的。
三、被所有对象所共享
四、可以直接被类名所调用。
      实例变量和类变量的区别:
一、存放位置。
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
二、生命周期
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
静态使用注意事项:
1.静态方法只能访问静态成员。
        非静态方法既可以访问静态也可以访问非静态。
2.静态方法中不可以定义this和super关键字。
   因为静态优先于对象存在。所以静态方法中不可以出现this.
3.  主函数是静态的。
     静态有利有弊:
利处: 对对象的共享数据进行单独空间存储,节省空间。没有必要每一个对象中都存储一份。
     可以直接被类名调用。
弊端:生命周期过长
    访问出现局限性,(静态虽好,只能访问静态)。
什么时候使用静态?
要从两方面下手:
因为静态修饰的内容有成员变量和函数。
1、什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。
对象中的特有数据要定义成非静态存在于堆内存中。
2、什么时候定义静态函数??
  当功能内部没有访问到非静态数据(对象的特有数据),
  那么该功能可以定义成静态的。 
     class Poo{
String name;
public void show(){//此功能函数没有访问到非静态数据name,所以该功能因该定义成静态的
System.out.println("haha");
}
  }
 如下:
     class Poo{
String name;
public static void show(){
System.out.println("haha");
}
  }
写一个工具类,体会对静态的应用--工具类:
静态的应用:
每一个应用程序中都有共性的功能,我们可以将这些功能进行抽取,独立封装。以便复用。
虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。
但是我们发现:
1.对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。(实例变量) 。
2.操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。
 这时考虑,让程序更严谨,是不需要对象的。
 可以将ArrayTool中的方法都定义成static的。直接通过类名调用即可。
 将方法都静态后,可以方便与使用,但是该类还是可以建立对象的。
 为了更为严谨,强制让该类不能建立对象。
 可以通过将构造函数私有化完成。
//我的工具类
public class ArrayTool {
//构造函数私有化,保证了该类不能对其进行new 对象(创建对象)
//直接类名调用其内部方法,可以节省堆内存空间
private ArrayTool(){}
//取下标--得到最大值
public static int getMax(int[] arr){
int max=0;
for(int x=0;x<arr.length;x++){
if(arr[x]>arr[max]){
max=x;
}
}
return arr[max];
}
//去数组中的第一个数--比较后得到最大值
public static int getMax2(int[] arr){
int max=arr[0];
for(int x=1;x<arr.length;x++){
if(max<arr[x]){
max=arr[x];
}
}
return max;
}
//得到最小值
public static int getMin(int[] arr){
int min=0;
for(int x=0;x<arr.length;x++){
if(arr[min]>arr[x]){
min=x;
}
}
return arr[min];
}
//选择排序
public static void selectSort1(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]){
int temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
}
}
}
//冒泡排序
public static void selectSort(int[] arr){

for(int x=0;x<arr.length;x++){
for(int y=0;y<arr.length-x-1;y++){
if(arr[y]>arr[y+1]){
/*int temp=arr[y];
arr[y]=arr[y+1];
arr[y+1]=temp;*/
swap(arr,y,y+1);
}
}
}
}
private static void swap(int[] arr,int a,int b){//对外界隐藏
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
//打印数组
public static void printArr(int arr[]){
System.out.print("[");
for(int x=0;x<arr.length;x++){
if(x!=arr.length-1){
System.out.print(arr[x]+",");
} else{
System.out.print(arr[x]+"]");
}

}
}
}
一个类中默认会有一个空参数的构造函数。
这个默认的构造函数的权限和所属类一致。
如果类被public修饰,那么默认的构造函数也带public修饰符。
如果类没有被public修饰,那么默认构造函数,也没有public修饰。
默认构造函数的权限是随着类的变化而变化的。
2、静态代码块static{}    
   特点:随着类的加载而执行,只执行一次,并优先于主函数先执行。
   作用:用于给类进行初始化的。
区别于构造代码块{}是给对象进行初始化,优先于函数先执行,对象一建立就加载。
分析对象建立的过程:
 Person p=new Person();
 该句话都做了什么事情?
 1、因为new用到了Person.class所以会先找到Person.class文件并加载到内存中。
 2、执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
 3、在堆内存中开辟空间,分配内存地址。
 4、在对内存中建立对象的特有属性,并进行默认初始化。
 5、对属性进行显示初始化。
 6、对对象进行构造代码块初始化。
 7、对对象进行对应的构造函数初始化。
 8、将内存地址赋给栈内存中的p变量。
3、设计模式:解决某一类问题最行之有效的方法
   Java中有23种设计模式:
单例设计模式:解决一个类在内存中只存在一个对象。
想要保证对象唯一
1.为了避免其他程序过多建立该对象。先禁止其他程序建立该对象。
2.还为了其他程序可以访问到该类对象,只好在本类中自定义一个对象。
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
这三部怎么用代码体现呢?
1.将构造函数私有化。
2.在类中建立一个本类对象。
3.提供一个方法可以获取到该类的对象。
class Single{
    private Single(){}
Single s=new Single();
public Single getInctance(){
   return s;
}
}
我们想要通过一个方法返回这个本类对象则此方法的返回类型就是本类Single;
我们想要通过这个方法(getInctance())访问对象,但是有不能从新new对象,只有一种方法那就是必须通过类名调用,所以该方法必须用static修饰,由于静态方法在访问类中成员,所以该成员(该类对象)也必须是(static)静态的,而s又是类变量(静态变量),我们通常私有化(private),处理后:
//饿汉式:类一加载就在内存中创建了对象,开发时常用;
class Single{
    private Single(){}
private static Single s=new Single();
public static Single getInctance(){
   return s;
}
//其他方法......
}
//懒汉式:对象方法被调用时才进行初始化,也叫做对象的延迟加载,多个程序访问时有安全隐患。面试常用;
 Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。
class Single{
private static Single s=null;
    private Single(){}
public static Single getInctance(){
   if(s==null)
    s= new Single();
   return s;
}
//其他方法......
}
解决懒汉式的安全隐患:---》双重判断
class  Singleton{
private String name;//实例变量
//创建本类实例,只能被本类访问,先与对象创建
private static  Singleton single=null;
//构造函数私有化,禁止其他程序创建对象
private  Singleton(){}
//提供静态可以访问本类对象的功能
public static  Singleton getInctance(){
if(single==null){
synchronized (Singleton.class) {  //加锁机制
if(single==null){
single=new Singleton();
}
}
}
return single;
}
        public void setName(String name){
this.name=name;
}
public void speak(){//与特有数据相关联,就不static了
System.out.println("我叫"+name);
}
}
7.1、继承 关键字extends
      java继承是使用已存在的类的定义作为基础建立新类的技术 
1、变量
  如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this。
子类要访问父类中的同名变量,用super。
super的使用和this的使用几乎一致。
this代表的是本类对象的引用,super代表的是父类对象的引用。
class Fu{
  int num=23;
}
class Zi extends Fu{
  System.out.print(this.num);//super.num
  System.out.print(super.num);//父类引用指向子类对象
}
结果:23;
      23;
class Fu{
  int num=23;
}
class Zi extends Fu{
  int num=22;
 public void show(){
  System.out.print(this.num);
  System.out.print(super.num);
 }
}
结果:22;
     23;

父类引用指向子类对象----->多态
  super 指向new Zi().show();
2、函数
  子类中的函数:
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的功能。
如同父类的函数被覆盖一样。
这种情况是函数的另一个特性:重写(覆盖);
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽然具备该功能,但是功能的内容却和父类不一致 ,
这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。
覆盖:
1、子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2、静态只能覆盖静态。

重载与重写区别:
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。
结论:public int show(){}  与 public void show(){} 这两个函数并不是覆盖,编译会报错,
更不能同时出现在同一个函数中,因为JVM不能确定该调用哪个函数,所以编译失败!!
 1》子类中的构造函数:
  在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的   语句super();
构造函数都不能被覆盖(重写)
super():会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();
class Fu{
Fu(){
      System.out.println("Fu run");
     }
}
class Zi extends Fu{
      Zi(){
           //super();
       System.out.println("zi run");
      }
}
public class TestPerson {
public static void main(String[] args) {
new Zi();
}
结果:Fu run
      zi run

为什么子类一定要访问父类中的构造函数?
因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的的构造函数,可以手动定义super语句的方式来指定。

注意:super语句一定要定义在子类构造函数的第一行。
子类的实例化过程:
结论:
 子类中所有的构造函数,默认都会访问父类中的空参数的构造函数。
 因为子类每一个构造函数的第一行都有一句隐式的super();
 当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。
 当然:子类中的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
 子类中至少会有一个构造函数会访问父类中的构造函数。

3、final:最终。作为一个修饰符。  
1)  可以修饰类、函数  、变量。
2) 被final修饰的类不可以被继承。为了避免被继承,被子类覆写功能。
3) 被final修饰的方法不可以被覆写。也叫最终方法
4) 被final修饰的变量是一个常量,只能被赋值一次,既可以修饰成员变量,也可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便阅读。而这个值不需要改变,所以加上final修饰。
作为常量:常量书写规范,字母都大写,若有多个单词用_链接;
final double PI=3.14;

5) 内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。   


------- android培训java培训java博客、java学习型技术博客、期待与您交流! ----------

如有疑问:http://edu.csdn.net/



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_wangtao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值