zoukankan      html  css  js  c++  java
  • java学习笔记

    java数据类型的转换

    Java中可以进行不同数据类型的加减乘除运算吗?是可以的。在算术运算符中已经体验过如果两个整数(int)相除会去掉小数部分。如果需要保留小数部分,可以让除数或者被除数变为double类型的(5变为5.0)。其实Java是自动的将int的那个数变为了double类型了也就是Java自动的将整数变为了浮点数。例如5/2.0 其实是5.0/2.0

    1、 自动类型转换(也叫隐式类型转换)

        可以将一个数赋值给更大数值范围的变量,例如可以经byte 变量赋值给short变量可以将short变量赋值给int变量可以将int变量赋值给long变量。

    Java内部其实做了工作就是自动将数值进行了类型提升,就叫做自动类型转换(也叫隐式类型转换)

    byte b = 1; //00000001

           short s = b;  //00000000 00000001

           int i = s;

           long lon = i;

           double d = lon; //1.0

    自动类型转换(也叫隐式类型转换)

    要实现自动类型的转换,需要满足两个条件,第一两种类型彼此兼容,第二目标类型取

    值范围必须大于源类型。所有的数字类型,包括整形和浮点型彼此都可以进行转换。

    例如:

    byte b=100;

           int x=b;

           System.out.println(x);//程序把b结果自动转换为int类型。

    2、 强制类型转换(也叫显式类型转换)

    不可以将一个数值赋给范围更小数值范围的变量,除非进行类型转换。

    byte b = 100;

           b = b + 2;

           System.out.println(b);

    上述例子发生了什么,发生了类型转换。

    b+2 遇到了加法运算,2默认是int类型,byte类型b变量存储的值自动类型提升为

    了int类型。执行完加法运算后的结果就是int类型,想要将int的类型值放入到byte类型变量b中,无法放入,编译报错。

    byte b=1;

           b=(byte)(b+2);

    当两种类型彼此不兼容,或者目标类型取值范围小于源类型(目标是byte源是int)

    无法自动转换,此时就需要进行强制类型转换。

    1、 什么时候要用强制类型转换

       比如小数部分只想保留整数部分.

       一定要清楚要转换的数据在转换后数据的范围内否则会损失精度.

    public static void main(String[] args) {

           byte b = 100;

           b = (byte) (b + 2);

           System.out.println(b); // 102

            //舍弃小数部分

            double d=5.5;

           int num=(int)d;

    }

    2、 表达式的数据类型自动提升

    算术表达式,逻辑表达式                                   

    所有的byte型、short型和char的值将被提升到int型。

    如果一个操作数是long型,计算结果就是long型;

    如果一个操作数是float型,计算结果就是float型;

    如果一个操作数是double型,计算结果就是double型。

    分析 System.out.println(‘a’+1)结果?

    自动类型提升

      

    byte b = 3;

           int x = 4;

           x = x + b;// b会自动提升为int 类型参与运算。

           System.out.println(x);// 7

    强制类型转换

    byte b = 2;

           /*

            * 强制类型转换,强制将b+2强制转换为byte类型,再赋值给b

            */

           b = (byte) (b + 2);

           System.out.println(b);// 4

    思考1

    byte  b=126;

    问:既然数据默认的有数据类型,那么126 默认是int类型的,为什么存储到byte类型时不会报错呢。

    126 是常量java在编译时期会检查该常量(每个常量)是否超出byte类型的范围。如果没有可以赋值。

    思考2:byte b=128;能否正常的编译和运行。

    该语句会出现编译错误,128超出了byte变量的存储范围,所以出现编译错误。

    文档注释用/** */表示,是java特有的注释,其中注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。

    java中byte变量的范围是  -128~127

     Math.random()的简单使用

     Math.random()可以使系统默认随机选取大于等于0.0且小于1.0的伪随机Double值,是java语言常用的代码

          

    int i=(int)(Math.random()*21); 

    Scanner的基本使用

    Scanner 被称为输入流扫描器类,从控制台读取数据的 String nextLine() 从控制台返回一行,忽略空格。

    int: nextInt() 从控制台返回一个 int 型数据,如果时间格式不对将抛出。java.util.InputMismatchException。 long: nextLong() 从控制台返回一个 long 型数据,如果时间格式不对将抛出java.util.InputMismatchException。 float: nextFloat() 从控制台返回一个 float 型数据,如果时间格式不对将抛出java.util.InputMismatchException。 double: nextDouble() 从控制台返回一个 double 型数据,如果时间格式不对将抛出java.util.InputMismatchException。 boolean: hasNext() 判断输入流还有没有下一个数据 ,
    首先要好导入包:import java.util.Scanner;或者java.util.*

    java.util是一个包名,java.util.*代表该包内的所有类
    例子:
    
    
     1   import java.util.Scanner;
     2  public class TextScanner{
     3   public static void main(String [] args){
     4 //创建Scanner对象 接受从控制台输入
     5  Scanner input = new Scanner(System.in);
     6  System.out.println("请输入名字:");
     7  //接受String型
     8  String name = input.next();//注意不是nextString()
     9 System.out.println("请输入学号");
    10   //接受int型
    11  int id = input.nextInt();//什么类型next后面就接什么 注意大小写
    12   //输出结果
    13  System.out.println("名字为:"+name+"	学号为:"+id);
    14    }
    15  }


    CompareToIgnoreCase的使用

    提示: musics[i].compareToIgnoreCase(music) > 0
    上面这个方法是比较字符串的方法,
    前面的值减 去后面的值,比如 :"aa".compareToIgnoreCase("cc")的值是-2      如果前面的值大返回正数,如果后面的大于前面的,返回负数,或者等于前面的,返回0

    例如 “Haha".compareToIgnoreCase("Aha") 是比较 haha 字符串 和 aha字符串 (此方法自动忽略大小写)
    h 比 a 大, 所以返回 是 7(相减得来的), (根据字母表顺序)

    Java中的构造方法:

    就和OC里面的自定义初始化方法一样,为了在创建对象的时候就给对象属性赋初始值,并且只走一次,因为第二次的话又是另一个对象了

     使用构造器时需要记住:

    1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名)

    2.每个类可以有一个以上的构造器

    3.构造器可以有0个、1个或1个以上的参数

    4.构造器没有返回值,前面不能有 void 

    5.构造器总是伴随着new操作一起调用,注意:不是手动调用的,而是java虚拟机自动调用的

    举例:

     1 public class A{
     2    public A(){
     3       System.out.println("调用了无参的构造函数");
     4    }
     5    public A(String mess){
     6       System.out.println("调用了有参的构造函数
    "+
     7          "参数内容为:"+mess);
     8    }
     9 }
    10 public class Test{
    11    public static void main(String [] args){
    12        A a_1=new A();//调用无参的构造函数
    13        A a_2=new A("Hello");//调用有参的构造函数
    14    }
    15 }

    效果图:

    在继承中使用构造方法:

    默认情况下是自动调用父类的无参构造方法,如果使用super调用父类构造器的语句必须是子类构造器的第一条语句,不信的话,你可以试试,果断的报以下的错误:

    如果子类构造器没有显式地调用父类的构造器,则将自动调用父类的默认(没有参数)的构造器。如果父类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用父类的构造器,则java编译器将报告错误

    text.java文件代码:

     1  class A{
     2    public A(){
     3       System.out.println("调用了A的无参构造函数");
     4    }
     5    public A(String mess){
     6       System.out.println("调用了A的有参的构造函数
    "+
     7          "参数内容为:"+mess);
     8    }
     9 }
    10  class B extends A{
    11    public B(){
    12          System.out.println("调用了B的无参构造函数");
    13    }
    14    public B(String mess){
    15       super(mess);     //如果没有这句就会默认调用父类的无参构造方法
    16       System.out.println("调用了B的有参构造函数
    "+
    17          "参数内容为:"+mess);
    18    }
    19 }
    20 public class text{
    21    public static void main(String [] args){
    22        B b_01=new B();
    23        B b_02=new B("你好");
    24    }
    25 }

    效果图上:

    如果把15行的代码删了,就会这样:

    toString方法的作用:

    Object类提供的toString()方法总是返回该对象实现类的”类名+@+hashCode”值,这个返回值不能真正实现“自我描述”功能如图:

    当Java对象和字符串进行连接运算时,系统自动调用Java对象toString()方法返回值和字符串进行连接运算下面代码效果相同

    String pStr=p+”字符串”;

    StringpStr=p.toString()+”字符串”;

    test.java里面的代码:

     1 public class test {    
     2      
     3     public static class User{
     4         String name;
     5         int age;
     6         public User(String name,int age){
     7             this.name = name;
     8             this.age = age;
     9         }
    10         @Override
    11         public String toString() {
    12             return "my name is "+name+",i'm "+age+" years old";
    13         }
    14          
    15     }
    16     public static void main(String[] args) {
    17         System.out.println(new User("Jack",16));
    18     }
    19 }

    效果图上:

    其中,@Override的作用:

     系统可以帮你检查方法的正确性,@Overridepublic String toString(){...}这是正确的一旦写错 写成这样@Overridepublic String tostring(){...}编译器可以检测出这种写法是错误的 这样能保证你的确重写的方确而如果不加@Overridepublic String tostring(){...}这样编译器是不会报错的 它只会认为这是你自己新加的一个方法仅此而已,说白了,就是试图覆盖父类方法而确又写错了方法名时才发挥威力的。

    Java中的静态的理解与main函数为什么是静态的?(static)

     首先理解什么是static,java中的static有什么作用?

    在C语言中的static表示只初始化一次,而在这java中也一样,不过还多了一些功能,被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。要这个类被加载,Java虚拟机(JVM)就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

    static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为: 

    类名.静态方法名(参数列表...) 

    类名.静态变量

    静态方法可以直接通过类名调用,任何的实例也都可以调用,

    因此静态方法中不能用thissuper关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。

    理解了这些后,我们就可以上代码

    1 public class text {    
    2 
    3     public  void main(String[] args) {
    4         System.out.println("dfdfd");
    5     }
    6 }

    编绎通过了,但运行就报错了,如图:

    原因是

    静态成员函数在执行前必须先构造并实例化该函数所在的类,也就是说必须先创建 一个对象。

    如果允许非静态的main,那么main函数所在的类必须先进行实例化,那么就需要再写个函数去实例化main所在的类,再调用main,这个实例化代码又写在哪呢?如果它也是非静态的,那就又要写这个实例化代码,那还有完没完啊??!!因此,没有为什么!JAVA语言就规定了main必须是静态的。

    构造方法的前面为什么不能是静态的

    我们由浅入深,首先看代码:

     1 public class text {    
     2  class People
     3  {
     4      int id;
     5      String name;
     6      int age;
     7      public People(String name,int age){
     8        this.name=name;
     9        this.age=age;
    10        System.out.println(this.name+this.age);
    11      }
    12  }
    13     public static void main(String[] args) {
    14         System.out.println(new People("Jack",16));
    15     }
    16 }

    编绎就报错了,如图:

    原因是:

    this 是指向当前对象的引用,需要对象实例化以后才能赋值。而静态成员都是类所属的,不需要对实例化就可以使用,所以在静态上下文中引用this(可以理解为空指针)时可能其还未赋值,所以应不能这样使用。this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this。说白了,就是不能用类来调用
    分析:
    People成了text的非静态内部类,属于text的一个成员,在静态方法main中不能访问非静态的成员,也就是说不能直接new Clerk()只能通过外部类的对象访问(创建一个对象)。

    所以我们可以这样:

     1 public class text {    
     2  class People
     3  {
     4      int id;
     5      String name;
     6      int age;
     7      public People(String name,int age){
     8        this.name=name;
     9        this.age=age;
    10        System.out.println(this.name+this.age);
    11      }
    12  }
    13     public static void main(String[] args) {
    14         System.out.println(new text().new People("Jack",16));
    15     }
    16 }

    编绎运行通过 :

    Java中有明文规定,类变量不能直接访问实例变量实例变量可以(但不推荐)能访问类变量,所以说一个static修饰的变量在调用普通方法;或一个static修饰的方法在调用普通变量,这是不允许的。

    两者的区别是: 

     对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。 
     对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
    总结:
    静态的可以访问静态的,静态的不能访问非静态的,非静态的可以访问静态的(因为静态的我个人理解是在JVM编绎时就存在了,与虚拟机共存死亡,而非静态的还不一定存在,所以理解很简单)

    如果是在构造方法的前面加上修饰符static ,就会报错,如图:

    原因是:

    java中构造方法可以有任何访问的修饰符,public、private、protected或者没有修饰符 ,都可以对构造方法进行修饰。不同于实例方法的是构造方法不能有任何非访问性质的修饰符修饰,例如static、final、synchronized、abstract等都不能修饰构造方法。

    解释:构造方法用于初始化一个实例对象,所以static修饰是没有任何意义的;多个线程不会同时创建内存地址相同的同一个对象,所以synchronized修饰没有意义;
    构造方法不能被子类继承,所以final和abstract修饰没有意义。
    2、返回类型是非常重要的,实例方法可以返回任何类型的值或者是无返回值(void),而构造方法是没有返回类型的,void是空类型,所以void也不行。
    3、至于命名就是构造方法与类名相同,当然了实例方法也可以与类名相同,但是习惯上我们为实例方法命名的时候通常是小写的,另一方面也是与构造方法区分开。
    而构造方法与类名相同,所以首字母一般大写。
    注意:构造方法中可以调用普通(实例)方法和构造方法的
    直接上代码:调用普通方法
     1 public class text {    
     2  class People
     3  {
     4      int id;
     5      String name;
     6      int age;
     7      public  People(String name,int age){
     8        this.name=name;
     9        this.age=age;
    10        System.out.println(this.name+this.age);
    11        fun2();
    12      }
    13 
    14      public void fun2(){
    15          System.out.println("ceshi2");
    16      }
    17  }
    18     public static void main(String[] args) {
    19         System.out.println(new text().new People("Jack",16));
    20     }
    21 }

    效果图上:

    构造方法中调用构造方法:

     1 public class text {    
     2  class People
     3  {
     4      int id;
     5      String name;
     6      int age;
     7      public  People(String name,int age){
     8        this.name=name;
     9        this.age=age;
    10        System.out.println(this.name+this.age);
    11        this();
    12        this(20);
    13      }
    14       public  People(){
    15        System.out.println("调用默认的构造方法");
    16      }
    17       public  People(int age){
    18 
    19        System.out.println("调用有参数的构造方法,参数是:"+age);
    20      }
    21     
    22  }
    23     public static void main(String[] args) {
    24         System.out.println(new text().new People("Jack",16));
    25     }
    26 }

    编绎就报错了:

    因此得改成这样的:

     1 public class text {    
     2  class People
     3  {
     4      int id;
     5      String name;
     6      int age;
     7      public  People(String name,int age){
     8        this();
     9        //this(20);     //一个构造方法里面只能调用一个构造方法,加上这个就会报错了
    10        this.name=name;
    11        this.age=age;
    12        System.out.println(this.name+this.age);
    13      }
    14       public  People(){
    15            this(20);
    16        System.out.println("调用默认的构造方法");
    17      }
    18       public  People(int age){
    19 
    20        System.out.println("调用有参数的构造方法,参数是:"+age);
    21      }
    22     
    23  }
    24     public static void main(String[] args) {
    25         System.out.println(new text().new People("Jack",16));
    26     }
    27 }

    效果图:

    结论:在构造方法中可以调用普通方法(对象方法),也可以在构造方法中调用构造方法,格式是:this(参数名,没有的话就不填),并且必须是第一条语句 且只能有一条。

    构造代码块的使用与理解:

    普通代码块:是最常见的代码块,在方法里用一对“{}”括起来的数据,就是普通的代码块,

    构造代码块:是在类中直接定义的,用“{}”括起来的代码。每次调用构造方法前执行,都会先执行构造代码块。

    静态代码块:他在类中的成员位置,用“{}”括起来的代码。只不过他用了static修饰了,,且执行一次

     代码块测试题:结合了,普通代码块,构造代码块,静态代码块,是大家能够够清楚的明白代码块执行的数序以及规律

    他会先执行class 文件class Nihaoa到内存。所以他会执行class Nihaoa类下的静态块,在执行main方法,编译class GouZao类,然后执行代码,静态的执行一次,构造方法块每次执行

    静态内部粝与非静态内部类的使用与理解 

    什么是内部类?就是在类中再定义类的类就叫做内部类。

    首先先看静态内部类,代码:

     1 public class text {   
     2     int a=0;
     3     static int b=0;
     4 public static class People
     5  {
     6      int id;
     7      String name;
     8      int age;
     9      public  People(String name,int age){
    10         this.name=name;
    11         this.age=age;
    12         fun1();
    13         //fun2();
    14         //System.out.println("name is:"+name+"  age is:"+a);
    15         System.out.println("name is:"+name+"  age is:"+b);
    16      }
    17  }
    18  public  static void fun1(){
    19     System.out.println("调用静态的方法");
    20  }
    21   public  void fun2(){
    22     System.out.println("调用非静态的方法");
    23  }
    24     public static void main(String[] args) {
    25         System.out.println(new People("Jack",16));
    26     }
    27 }

    运行通过,效果:

    如果把注释部分去掉后,就会报错,如图:

    因此,得出:静态内部类的非静态成员(比如this)可以访问外部类的静态变量/静态方法,而不可访问外部类的非静态变量/非静态方法;

    再来看非静态内部类:

     1 public class text {   
     2 public  class People
     3  {
     4      int id;
     5      String name;
     6      int static age;
     7      public  People(String name,int age){
     8         this.name=name;
     9         this.age=age;
    10         System.out.println("name is:"+name+"  age is:"+age);
    11      }
    12  }
    13     public static void main(String[] args) {
    14         System.out.println(new People("Jack",16));
    15     }
    16 }

    运行效果图:

    得出:非静态内部类则不能有静态成员。为什么?

    假设要访问非静态内部类里的静态成员,由于是非静态内部类,那么必须先声明外部类的实例(也就是对象)才行,内部类也会被初始化,这时就变成对象调用,这就不符合静态的作用了(因为没意义)

    其实总结就一句话,静态的可以访问任何静态的,因为在JVM时就分配了内存(个人理解),不能访问非静态的,非静态的可以访问任何静态的,非静态的要访问非静态的,要实例化对象才行。

    单例设计模式:

    所谓的单例设计模式:顾名思义就是全局就一个对象(一个地址)

     1 /*
     2     单例设计模式 : 一个类只能够创建一个对象出来
     3     软件行业中设计模式23中
     4     可能在java学习中会讲到如下设计模式:
     5         1.单例设计模式
     6         2.观察者设计模式
     7         3.模块设计模式(mvc)
     8         4.装饰设计模式
     9         5.工厂模式
    10     
    11     设计模式 : 用来解决同一类问题的解决方案(固定的步骤)
    12 
    13     单例的设置步骤:
    14         1.创建一个对象把他设置为私有的静态成员变量,保证对象唯一
    15         2.把构造方法设置为私有的,防止new一个对象。
    16         3.定义一个公开的静态方法,返回值为上面的对象。
    17         
    18 
    19 */
    20 
    21 /*
    22     oc中单例:
    23     +(SingleDog *)default{
    24 
    25         //保证对象唯一
    26         static SingleDog s;
    27         if(s == null){
    28           s = [[SingleDo alloc] init];
    29         }
    30         return s;
    31     }
    32 
    33     
    34     
    35 
    36 
    37 */
    38 
    39 
    40 //如何实现单例设计模式
    41 //--------饿汉单例设计模式
    42 class SingleDog{
    43     
    44     String name;
    45     int  age;
    46     //保证对象唯一
    47     // 声明本类的引用变量, 并且把对象创建出来
    48     private static SingleDog  s = new SingleDog(); // 静态的成员变量
    49     //私有化构造方法 ,防止通过new来创建对象
    50     private SingleDog(){}
    51     //提供一个静态方法来接收唯一的对象
    52     public static SingleDog getInstance (){
    53     
    54         return s;
    55     }
    56 
    57 }
    58 
    59 //------------懒汉单例设计模式--------------
    60 //不安全  ,推荐使用上面的写法。
    61 class SingleDog2 {
    62 
    63     //声明本类的引用变量,不创建
    64     private static SingleDog2 s;
    65     
    66     //私有化一个构造方法
    67     private SingleDog2() {};
    68     
    69     //提供一个静态的方法来接收唯一的对象
    70     public static SingleDog2 getInstance(){
    71         
    72         if(s==null){
    73             
    74             s = new SingleDog2();   
    75         }
    76 
    77         return s;
    78 
    79     }
    80 }
    81 
    82 class Demo7 {
    83     public static void main(String[] args){
    84 
    85         SingleDog  sd1 = SingleDog.getInstance();
    86         sd1.name = "老王";
    87         SingleDog  sd2 = SingleDog.getInstance();
    88         SingleDog  sd3 = SingleDog.getInstance();
    89 
    90         System.out.println(sd1);
    91         System.out.println(sd2);
    92         System.out.println(sd3);
    93     }
    94 }

    在50行和67行用到了private,表示是私有的,外部的类不能访问,如果访问就报错,即对内可见,对外不见,所以我们常常把单例对象封装在一个类中,比如主函数在该类中,那么private就没有意义了,因为有没有都一样的。如:

     1 public  class a{
     2    static class People{
     3      private static People p = new People();
     4        //重写默认的构造方法
     5         private People(){
     6          System.out.println("dfdfdfdfdf");
     7         };
     8         public static People getInstance(){
     9          return p;  
    10         }
    11     }
    12    public static void main(String[] args){
    13            People sss = new People();  //这一句没有报错,因此private就没有意义了
    14            People s=People.getInstance();
    15             People ss=People.getInstance();
    16            System.out.println(s);
    17           System.out.println(ss);
    18          }
    19 }

    效果图:

    抽象类的使用与理解(注意与interface的区别):

    abstract(抽象类)的使用(与interface的区别): 

    所谓的抽象类就好比一道 抽象的数学题,你一步步做出来了就觉得很简单了,而在java中抽象类是abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例(因为方法有可能是抽象方法,没有实现,那就没意义了),可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法,不然就会报错,并且抽象方法必须在抽象类中。

    标准概念:

    面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

    代码:

    1 public  class a{
    2          abstract static class People{
    3       }
    4    public static void main(String[] args){
    5          People p = new People();
    6          }
    7 }

    运行结果:

    抽象方法是没有方法体的(也就是没有大括号,只有声明,没有实现,类似于OC中的protocol),留给子类去实现。

    1 public  class a{
    2          abstract static class People{
    3              //abstract void fun();  //这是对的
    4              abstract void fun(){}    //不能方法体,这样写是错误的
    5       }
    6    public static void main(String[] args){
    7          }
    8 }

    编译:

    一个抽象类中是可以有非抽象的方法,并且也可以不出现抽象方法的,如:

     1 public  class a{
     2          abstract static class People{
     3              //String name;
     4              //abstract void fun();  //这是对的
     5             // abstract void fun(){}    //不能方法体,这样写是错误的
     6              void fun1(){
     7               System.out.println("haha");  //抽象类中是可以定义非抽象方法的
     8             }
     9       }
    10       class Student extends People
    11       {
    12            public Student(){
    13              fun1();
    14            }
    15       }
    16    public static void main(String[] args){
    17          Student s = new a().new Student();
    18          }
    19 }

    运行:

    一个抽象类中是可以存在构造方法。作用是让子类能过初始化父类中的变量。如:

     1 public  class a{
     2          abstract static class People{
     3              String name;
     4              //abstract void fun();  //这是对的
     5             // abstract void fun(){}    //不能方法体,这样写是错误的
     6              void fun1(){
     7               System.out.println("name is :"+ name);  //抽象类中是可以定义非抽象方法的
     8                
     9             }
    10            public People(){   //抽象类的构造方法的作用是用于初始化成员变量
    11               name = "yuan";   
    12            }
    13       }
    14       class Student extends People
    15       {
    16            public Student(){
    17              fun1();
    18            }
    19       }
    20    public static void main(String[] args){
    21          Student s = new a().new Student();
    22          }
    23 }

    运行:

    总结:

    1,abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法。

    2,abstract修饰方法,会使这个方法变成抽象方法,声明(定义)而没有实现,实现部分以";"代替。需要子类继承实现(覆盖)。

    3.abstract修饰符在修饰类时必须放在类名前。

    4.abstract修饰方法就是要求其子类覆盖(实现)这个方法。调用时可以以多态方式调用子类覆盖(实现)后的方法,也就是说抽象方法必须在其子类中实现,除非子类本身也是抽象类。

    5.父类是抽象类,有抽象方法,子类继承父类,并把父类中的所有抽象方法都实现(覆盖),抽象类中有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。

    abstract能修饰成员变量吗??

    答:不能。原因:只有public, protected, private, static, final, transient 和 volatile 能修饰成员变量。

    abstract关键字的使用场景:
    我们在描述一个事物的时候,发现这个事物确实存在某种行为,但是这种行为又不具体,那么这个时候就可以抽取这种行为 声明一个没有实现的行为,这种行为就叫抽象的行为,那么这个时候就需要用到抽象类。

    使用abstract时需要注意:

    1、不能和private一起使用。原因:abstract声明的方法必须要被重写,如果设为private就互相矛盾了

    2、不能和static使用。原因:因为static 方法是类方法,必须要有方法体(也就是实现),就像main函数,有且仅有一个,它是不允许子类覆写,而且而abstract方法是没有实现的方法,是必须由子类来覆写的,两者完全矛盾,你说呢?

    3、不能和final一起使用。原因:final修饰过的是不能修改的,而且必须要初始化,而abstract必须得重写才行,矛盾了。

  • 相关阅读:
    python学习之关于变量与内存的问题
    [题解]GDUT 2020年11月赛DE题
    【转】关于Oracle默认用户名system密码不正确登录不上解决方案
    [转载] Monitor Tools
    java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getAsyncContext()Ljavax/servlet/AsyncContext;
    【SSM】Result Maps collection already contains value for crud.dao.EmployeeMapper.BaseResultMap
    EL表达式失效,页面取不到数据
    处理回归BUG最佳实践
    固定QPS压测初试
    Java字符串到数组的转换--最后放大招
  • 原文地址:https://www.cnblogs.com/qq1871707128/p/6056548.html
Copyright © 2011-2022 走看看