栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java学习(第二周)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java学习(第二周)

在这一周的学习中,我学了面对对象这一章,这一章相比于C++多了许多新东西,同时这一章也是Java学习中的关键部分,所以我对此下了很大功夫。

面向对象具有三大特征:封装性、继承性和多态性,而面向过程没有继承性和多态性,并且面向过程的封装只是封装功能,而面向对象可以封装数据和功能。所以面向对象优势更明显。

四.Java面对对象

栈的特点如下:

  1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)

  2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)

  3. 栈属于线程私有,不能实现线程间的共享!

  4. 栈的存储特性是“先进后出,后进先出”

  5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

堆的特点如下:

  1. 堆用于存储创建好的对象和数组(数组也是对象)

  2. JVM只有一个堆,被所有线程共享

  3. 堆是一个不连续的内存空间,分配灵活,速度慢!

方法区(又叫静态区)特点如下:

  1. JVM只有一个方法区,被所有线程共享!

  2. 方法区实际也是堆,只是用于存储类、常量相关的信息!

  3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)

this

this的本质就是“创建好的对象的地址”! 由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表“当前对象” 。

C++中是this->name;

而在Java中为this.name=name;

super 可以用来修饰属性,方法,构造器
f(){}

super.f();

构造方法的第一句总是super()

1、当子类与父类有同名的属性时,可以通过super属性的方式调用父类中生命的属性。

2、当子类重写父类的方法后,在子类中若想调用父类中被重写的方法时,需用super.的方法

3、super修饰构造器,通过在子类中使用super列表参数的形式调用父类中制定的构造器

        a、在构造器内部,super(参数列表)必须声明在首行

        b、在构造器内部,this(参数列表)或super(参数列表)只能出现一个

        c、当构造器中不显示的调用this(参数列表)或super(参数列表)默认调用父类中的空参                 构造器

public childclass extends fatherclass{

   public childclass(){

          super();//默认的

           System.out.println();

    }

}     //子->父->object



注意:在类中,用static声明的成员变量为静态成员变量,也称为类变量static成员变量只有一份。被该类的所有对象共享!!在static方法中不可直接访问非static的成员。

static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象的。

没有static需要有对象才能调用。加static可直接调用,不用再new。

为什么this super不能用在static方法中

this : 代表当前自身类的对象,可以调用当前类的构造方法,成员变量和成员方法等

super : 代表对父类的引用 , 可以调用父类构造方法,成员变量和方法

因为static方法和类的实例(对象)是两码事,它只在类装载的时候初始化,被称作类级变量(属于类);而类的实例是在程序运行的时候(即Java命令的时候)初始化,被称作对象级变量(属于对象);

this表示这个类的当前实例,super表示父类的当前实例,static是属于类的,this是类的一个对象,

this指针是指向类的对象,在实例化对象时jvm会在堆区分配内存给一个具体的对象,this指针指向这个对象。而类中的static域始终是在静态区分配内存,this指向堆区,所以不能调用。

因此this super不能用在static方法中

Package

为了便于管理,将处理同一方面的问题的类放在同一个目录下,引入了包

包定义:

package 包名;    //声明

package(包)  域名倒着写 cn.gst.oo

cn.gst.oo.User user=new cn.gst.oo.User();(有点繁琐)  //使用其他包的类

//使用其他包的类,用import.   import cn.gst.oo.User;

使用 import 导入单个类    import 包名+类名;

直接导入指定类   import example.Test;

使用 import 语句导入指定包下全部类  import example.*;

单例模式 :  只有一个实例存在,给别的类用

什么是单例模式?

1. 构造方法私有化

2. 静态属性指向实例

3. public static的 getInstance方法,返回第二步的静态属性

饿汉式单例模式:未使用就已经实例化。
//GiantDragon 提供了一个public static的getInstance方法,外部调用者通过该方法获取12行定义的对象,而且每一次都是获取同一个对象。 从而达到单例的目的。
private test(){        //通过私有化其构造方法,使得外部无法通过new 得到新的实例。
         
    } 
private static test instance = new test();//准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个
 public static txst getInstance(){   //public static 方法,提供给调用者获取定义的对象
        return instance;                   
    }

懒汉式单例模式:使用时才实例化。
 private test(){       //私有化构造方法使得该类无法在外部通过new 进行实例化
    }
private static test instance=null;  //准备一个类属性,用于指向一个实例化对象,但是暂时指向null

public static test getInstance(){  //public static 方法,返回实例对象

if(null==instance){      //第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象

            instance = new test();   //返回 instance指向的对象

        }

什么时候使用饿汉式,什么时候使用懒汉式:

饿汉式是立即加载的方式,无论是否会用到这个对象,都会加载。


懒汉式,是延迟加载的方式,只有使用的时候才会加载。 
使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。

有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式

类型转换:

子类转父类(向上转型),一定可以的

 父类转子类(向下转型),所以要进行强转

instanceof  类名 判断一个引用所指向的对象,是否是父类,或者子类

(二元运算符,左边是对象,右边是类,当是右边类或子类创建的对象时,返回true,否则返回false)

Object obj = new String("  ");
        if(obj instanceof String){    //判断所指向的对象
            String str = (String)obj;
            System.out.println(str.charAt(0));
        }else if(obj instanceof StringBuffer){
            StringBuffer str = (StringBuffer) obj;
            System.out.println(str.charAt(0));
        }

向上转型:父亲引用指向子类对象或者 子类转为父类(小转大,不需要强转)

向下转型:子类引用指向父类对象 或者父类转子类(大转小,需强转)

C++在类中默认private,Java默认为default                                         
修饰符同一个类同一个包 子类所有类
private
default
protected
public  

final

1.修饰变量:被他修饰的变量不可改变,一旦赋了初始值,就不能被重新赋值

2.修饰方法:该方法不可被子类重写,但可以被重载

3.修饰类:修饰的类不能被继承。例如String,Math。

4.修饰引用:h引用被修饰成final,表示该引用只有1次指向对象的机会,依然通过h引用修改对象的属性值hp,因为hp并没有final修饰

final Hero h;

        h  =new Hero();

        h  =new Hero();//错误

        h.hp = 5;

5.常量指的是可以公开,直接访问,不会变化的值

 public static final int itemTotalNumber = 6;

①  首先介绍一下String类中常用的方法

1.在java中共有三种方法将两个字符串连接 第一种方法:使用+;
public static  String mergedString1(String string1,String string2) {
		return   string1 + string2;
	}
 第二种方法:使用concat();
public static String mergedString2(String string1, String string2) {
		return string1.concat(string2);
	}
 第三种方法:使用append();
public static  StringBuffer mergedString3(String string1, String string2) {
		StringBuffer sb = new StringBuffer(string1);
		return sb.append(string2);
		
	}

2.判断两个String对象相等
String str1 = "the light";
String str2 = new String(str1);
System.out.println( str1  ==  str2); //false

str1和str2的内容一定是一样的!但是,并不是同一个字符串对象

String str1="gg";
String str2="gg";     
System.out.println( str1  ==  str2); //true       

//编译器发现已经存在现成的"the light",那么就直接拿来使用,而没有进行重复创建

3.通常比较字符串时,用equals
String str1="gg";
String str2="gg"; 
System.out.println(str2.equals(str1)); //true

4.提取字符 :charAt()
String s1="love";
System.out.println(s1.charAt(3)); //输出为e

5.字符串的长度:length()
String s1="love";
System.out.println(s1.length());


 

6.比较两个字符串(忽略大小写):equalsIgnoreCase()
 
String s1="A";
String s2="a";
System.out.println(s2.equalsIgnoreCase(s1));  //忽略大小写    A==a; true

7.字符串中是否包含:indexOf()

System.out.println(s1.indexOf("Java"));//检测字符串s1中是否包含Jav

String s1 = "core Java";
System.out.println(s1.indexOf("Java"));//检测字符串s1中是否包含Java。true  
//若无返回-1。

8.替换 :replace()
String s1 = "core Java";
String s=s1.replace(' ','&');//将s1中空格换为&

9.是否以 ...开头startsWith()
String s1="How are you?";
System.out.println(s1.startsWith("How"));//是否以How开头

10.是否以...结尾:endsWith()
String s1="How are you?";
System.out.println(s1.endsWith("you"));//是否以you结尾

11.提取子字符串:substring()
String s=" ";
String s1="How are you?";
s=s1.substring(4);//提取子字符串,从4开始.  //are you?
System.out.println(s);
String s=" ";
String s1="How are you?";
s=s1.substring(4,7);//提取子字符串,从[4,7),不包括7,    //are
System.out.println(s);

12.转小写:toLowerCase()
String s1="H";
s=s1.toLowerCase();//.转小写
System.out.println(s);  //h

13.转大写:toUpperCase()
String s1="h";
s=s1.toUpperCase();//.转大写
System.out.println(s);  //H

14.去除收尾的字符串,中间不去:trim()
String s2="   How old are you!!  ";
s=s2.trim();   //去除收尾的字符串,中间不去
System.out.println(s);  //How old are you!!
System.out.println(s2);//   How old are you!!  //s2不变

抽象方法

      使用abstract修饰的方法,没有方法体,只有声明。定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现。

抽象类

      包含抽象方法的类就是抽象类。通过abstract方法定义规范,然后要求子类必须定义具

实现。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。

示例:

public abstract class Animal{   //规范子类
       abstract public void shout();
        public static void main(String[] args){
         Animal a=new Animal();//错误
         Animal a=new Dog();
         }
}   ; //子类必须实现
class Dog  extends  Animal{
    public void  shout(){
             System.out.println();//必须有
      }
}


为父类增加一个抽象方法 ,继承父类后,这些子类就必须提供不一样的抽象方法实现。

抽象类的使用要点:
1.有抽象方法的类只能定义成抽象类
2.抽象类不能实例化,即不能用new实例化
3.抽象化可以包含属性,方法,构造方法,但构造方法不能用来new实例,只能用来被子类调用
4.抽象类只能用来被继承
5.抽象方法只能被子类实现

实例化:只是单纯的把对象 new 一下就行了 例:Student st=new Student();这样就行了
初始化:是在实例化之后完成的,先实例化对象,只给对象属性赋值,然后初始化这个对象

在Java中引入了接口这个概念。

        接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。

       抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。

声明格式:

[访问修饰符]  interface 接口名   [extends  父接口1,父接口2…]  {
常量定义;  
方法定义;
}

定义接口的详细说明:

1.访问修饰符:可以是默认或者public
2.接口名:和类名采用相同命名机制
3.extends:接口可以多继承
4.常量:接口中的属性只能是常量, int M=111;
总是:public static final修饰,不写也是
5.方法:接口中的方法只能是public abstract,不写也是

注意:接口内所有方法多是抽象化,不用再写abstract ,因此必须重写。
关键字: implements(接口) 
 

java的类只有单继承,接口有多继承

抽象类和接口的区别:
区别1:子类只能继承一个抽象类,不能继承多个
             子类可以实现多个接口
区别2:抽象类可定义public,protected,package,private。静态和非静态属性。final和非final属性。
但是接口中声明的属性,只能是public,静态,final的,即便没有显式的声明。

接下来介绍一些  内部类

在Java中内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。

成员内部类(可以使用private、default、protected、public任意进行修饰。

a) 非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)

 i. 非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。

ii. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。

iii. 非静态内部类不能有静态方法、静态属性和静态初始化块。

iv. 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。

非静态内部类可以直接在一个类里面定义
实例化语法:  new 外部类().new 内部类() 或 外部类对象.new 非静态内部类();

public class 外部类 { 
    ...
    // 非静态内部类,只有一个外部类对象存在的时候,才有意义
    // 战斗成绩只有在一个英雄对象存在的时候才有意义
    class 非静态内部类 {     
     ...
        public void 方法名() {        
       ...
        }
    }
    public static void main(String[] args) {
        外部类 对象 = new 外部类();       // 实例化内部类
        // 非静态内部类对象只有在一个外部类对象存在的时候才有意义
        // 所以其实例化必须建立在一个外部类对象的基础之上
    }
}



在内部类中使用外部成员变量:  Outer.this.age    内部类名.this.外部成员变量。
在内部类中使用内部类的成员变量: this.age    this.内部成员变量
在内部类中使用局部变量:    age

b)静态内部类

 i. 定义方式:

static  class   ClassName {
//类体
}

 ii. 使用要点:

       1. 当一个静态内部类对象存在,并不一定存在对应的外部类对象。 因此,静态内部类的实例方法不能直接访问外部类的实例方法。

       2. 静态内部类看做外部类的一个静态成员。 因此,外部类的方法中可以通过:“静态内部类.名字”的方式访问静态内部类的静态成员,通过 new 静态内部类()访问静态内部类的实例。

在一个类里面声明一个静态内部类与非静态内部类不同,静态内部类的实例化 不需要一个外部类的实例为基础,可以直接实例化

除了可以访问外部类的私有静态成员外,静态内部类和普通类没什么大的区别
实例化语法:new 外部类.静态内部类();

匿名类

匿名类指的是在声明一个类的同时实例化它,使代码更加简洁精练
通常情况下,要使用一个接口或者抽象类,都必须创建一个子类
有的时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法。
既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。
这样的类,叫做匿名类

public abstract class 外部类 {
      ...
    public abstract void 方法();
    public static void main(String[] args) {
          
        外部类 对象 = new 外部类(){
            //当场实现方法
            public void 方法() {
               ...
            }
        };
        对象.方法();    
        System.out.println(对象); //通过打印对象,可以看到这个对象属于&&这么一个系统自动分配的类名
    }     
}

注意:  1. 匿名内部类没有访问修饰符。

           2. 匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。

//在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final。
注:在jdk8中,已经不需要强制修饰成final了,如果没有写final,不会报错,因为编译器偷偷的帮你加上了看不见的final

局部内部类

局部内部类是定义在方法内部的,作用域只限于本方法。

public class 外部类{
    public void 方法1() {
        //作用域仅限于该方法
        class 内部类 {
            public void 方法2() {
                ...
            }
        }
        new 内部类().方法2();
    }
    public static void main(String[] args) {
        new 外部类().方法1();
    }
}

本地类


本地类可以理解为有名字的匿名类
内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。
本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方

public abstract class 外部类 {
  ...  
    public abstract void 方法();
      
    public static void main(String[] args) {
          
        //与匿名类的区别在于,本地类有了自定义的类名
        class 本地类 extends 外部类
            public void 方法() {
                //进行重写
            }
        }
         
        本地类 对象  =new 本地类();
        对象.方法();
    }
      
}


 

默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法。

public interface 接口名 {
    public void 方法1();
    default public void 方法2() {   //接口增加了一个默认方法2,这个方法有实现体,并且被声明为了default
        ...
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/865265.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号