Java基础

Java语言基础组成:1.关键字  2.标识符  3.注释 4.变量和常量  5.运算符  6.语句 7.函数 8.数组
标识符:由26个英文字母大小写,数字:0-9 符号:- $组成
  规则:1.数字不可以开头
        2.不可以使用关键字
一. 数据类型:
1.引用数据类型:
包括类(class)  接口(interface) 和数组([ ])
2.基本数据类型:包括字符型(char)  布尔型(boolean) 和数值类型,而数值类型又包括整数类型(byte,short,int,long)和浮点类型(float,double)
3.注意:一般情况下整数默认为int ,小数默认为double
4.各类型所占二进制位数:

基本类型:byte二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127

基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767

基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647

基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807

基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38

基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308

基本类型:char二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535

5 单精度和双精度:
单精度:float的精度是6位有效数字,取值范围是10的-38到10的38次方占用4个字节
双精度:15位有数字,范围:10的-308到10的308次方占用8个字节
单精度和双精度的区别:双精度要比单精度所存储的位数更多,至于说3.14是双精度,是因为Java中,默认的小数都是double类型,也就是双精度的,如果要定义单精度的话,那就要在小数的后面加上f或者F,即double=3.14,float=3.14f。

6 关于基本数据类型的一个简单的例子:
1)语句 byte b=3;
 编译可以通过,因为3会自动判断是不是在b的范围内。
2)b=b+2 
  编译会报错 ,3是常量是固定的所以赋值给byte b,而b+2,b是变化的,不确定,当类型提升时会报错:可能会丢失精度。
3)b=(byte)(b+2)
强制类型转换,会把int类型的前3个8位砍掉。强制类型转换的应用,例如:把double转为int。提示:int与float作运算的时候结果为float, ' a'+1中的'a'也会进行自动类型提升结果为98。
7 一些关于计算机理论基础的运算符:
   >>代表右移  带符号右移就是将那个数转为2进制然后在前面补1或0
   如果是整数补0,负数补1
例:11>>2
0000 0000 0000 0000 0000 0000 0000 1011--->0000 0000 0000 0000 0000 0000 0000 0010
    -11>>2
1111 1111 1111 1111 1111 1111 1111 0101---->1111 1111 1111 1111 1111 1111 1111 1101
 ~代表反码 ;^代表异或 ;  &代表与
8 精确运算: 
<span style="font-family:SimSun;">double a=0.1;
double b=0.006;
System.out.println(a+b);</span>
打印结果为:0.106000 00001
    出现这种结果的原因是64位的double不能完全装下运算结果。
    如果想得到精确的结果要用到BigDecimal类。   

<span style="font-family:SimSun;">BigDecimal a=new BigDecimal("0.1");
BigDecimal b=new BigDecimal("0.006");
a.add(b);</span>

结果为:0.106   

9 自动装拆箱
java中数据类型分为两种 : 基本数据类型   引用数据类型(对象)
在 java程序中所有的数据都需要当做对象来处理,针对8种基本数据类型提供了包装类,如下:
int --> Integer
byte --> Byte
short --> Short
long --> Long
char --> Character
double --> Double
float --> Float
boolean --> Boolean
jdk5以前基本数据类型和包装类之间需要互转:
基本---引用   Integer x = new Integer(x);
引用---基本   int num = x.intValue();
1) Integer x = 1; x = x + 1;  经历了什么过程?装箱-->拆箱--> 装箱;
2) 为了优化,虚拟机为包装类提供了缓冲池,Integer池的大小 -128~127 一个字节的大小;
3) String池:Java为了优化字符串操作 提供了一个缓冲池;

二. 面向对象

     面向对象是基于面向过程而言的。
     面向对象和面向过程都是一种思想。
     面向过程:强调的是功能行为
     面向对象:将功能封装对象,强调具备功能的对象, 面向对象是基于面向过程的。

三 成员变量和局部变量

     作用范围:1.成员变量:作用于整个类中。 2.局部变量作用于方法中或者语句中。
     在内存中的位置:1.成员变量:在堆内存中,因为对象的存在,才在内存中存在。2.局部变量:存在栈内存中

四 封装

     封装:是指隐藏对象的属性和实现细节,仅对外提供访问方式。
     好处:1.将变化隔离  2.便于使用   3.提高重用性    4.提高安全性

     封装原则:1.将不需要对外提供的内容都隐藏起来 2.把属性都隐藏起来,提供公共方法对其访问

     1 单例设计模式:

     解决的问题:保证一个类在内存中的对象唯一性。

     实际应用比如:多程序读取一个配置文件时,建议配置文件封装成对象。会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中是唯一的。Runtime()方法就是单例模式设计出来的。

     2 如何保证对象唯一性呢?

     思想:

     1 不让其他程序创建该类对象。

     2 在本类中创建一个本类对象。

     3 对外提供方法,让其他程序获取这个对象。

    步骤:

     1 因为创建对象都需要构造函数初始化,只要将本类中的构造函数私有化,其他程序就无法再创建该类对象;

     2 就在类中创建一个本类的对象;

     3 定义一个方法,返回该对象,让其他程序可以通过方法就得到本类对象。(作用:可控)

    代码体现:

     1 私有化构造函数;

     2 创建私有并静态的本类对象;

     3 定义公有并静态的方法,返回该对象。

    示例代码如下:   

//饿汉式
class Single {
	private Single() {
	} // 私有化构造函数。

	private static Single s = new Single(); // 创建私有并静态的本类对象。

	public static Single getInstance() { // 定义公有并静态的方法,返回该对象。
		return s;
	}
}

// 懒汉式:延迟加载方式。
class Single2 {
	private Single2() {
	}

	private static Single2 s = null;

	public static Single2 getInstance() {
		if (s == null)
			s = new Single2();
		return s;
	}
}

五 构造函数:

    构造函数中不可以写return语句
    对象一建立就会调用与之对应的构造函数
    构造函数的作用:可以用于给对象进行初始化
    构造函数的小细节:当一个类中没有构造函数时,系统会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,默认的构造函数就没有了。
    当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。

六 构造函数代码块:

    构造代码块中定义的是不同对象共性的初始化内容
    作用:给对象进行初始化, 对象一建立就运行,且优先于构造函数执行
    和构造函数的区别:
    1.构造函数代码块是给所有对象进行统一初始化   
    2.而构造函数是给对应对象初始化,事例代码:           
<span style="font-family:SimSun;">class Person{
  {
    System.out.println("person");//构造代码块
   }
}</span>

七 this

this代表它所在函数所属对象的引用。即那个对象在调用this所在的函数,this就代表哪个对象。
this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。

八 静态

   1 用法: 是一个修饰符,用于修饰成员(成员变量,成员函数); 当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。类名.静态成员。
   2  static特点:
     1) 随着类的加载而加载;也就是说:静态会随着类的消失而消失。说明它的生命周期最长。
     2) 优先于对象存在 ; 明确一点:静态是存在,对象是后存在的。 
     3) 被所有对象所共享。
     4) 可以直接被类名调用。
    3 实例变量和类变量的区别:
     1) 存在位置: 类变量随着类的加载而存在于方法区中。 实例变量随着对象的建立而存在于堆内存中。
     2) 生命周期: 类变量生命周期最长,随着类的消失而消失,实例变量生命周期随着对象的消失而消失。
   4 静态的使用注意事项:
     1) 静态方法只能访问静态成员; 非静态方法既可以访问静态也可以访问非静态。
     2) 静态方法中不可以定义this,super关键字;  因为静态优先于对象存在。所以静态方法中不可以出现this。
    5 静态的利弊:
     利:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名 调用
     弊:生命周期过长。访问有局限(静态虽好,但只能静态访问静态)       
 九.多态
 1 多态的特点:

   1)多态的体现:
      父类的引用指向了自己的子类对象。 // Animal a = new Cat();
      父类的引用也可以接受自己的子类对象。
   2)多态的前提:
      必须是类与类之间有关系,要么继承要么实现。
      通常还有一个前提:存在覆盖。
   3)多态的好处:
      多态的出现大大的提高了程序的扩展性。
   4)多态的弊端:
      提高了扩展性但是只能使用父类的引用访问父类中成员,即不能访问子类成员。 ( 前期不能使用后期产生的功能,即访问的局限性 )
   5)转型:
      向上转型:类型提升。
      向下转型:强制将父类的引用转换成子类类型,向下转型。
   6)注意:
      千万不能出现这样的操作:就是将父类对象转成子类类型。
      多态自始至终都是子类对象在做着变化。
 2  在多态中非静态成员函数的特点:
    在编译时期:参阅引用类型变量所属的类中是否有调用的方法,如果有,编译通过。反之编译失败。
    在运行时期:参阅对象所属的类中是否有调用的方法。
      简单总结:成员函数在多态调用时,编译看左边,运行看右边。
 3 在多态中静态成员函数的特点:

    多态中成员变量的特点:无论编译还是运行,都参考左边(引用型变量所属的类)。
多态中静态成员函数的特点:无论编译和运行,都参考左边。
                静态绑定:静态方法一加载内存就被绑定在方法所属的类上。           

 反映静态和非静态在多态中区别的一段示例代码: 
class Father {
	static String sayHi() {

		return "Father say hi";
	}

	String name() {

		return "name is Father";
	}
}

class Son extends Father {
	static String sayHi() {

		return "Son say hi";
	}

	String name() {

		return "name is Son";
	}
}

class Differ {

	public static void main(String args[]) {
		Father s = new Son();
		System.out.println(s.sayHi() + "----" + s.name());
	}

}
                             
class Father {
	static String sayHi() {

		return "Father say hi";
	}

	String name() {

		return "name is Father";
	}
}

class Son extends Father {
	static String sayHi() {

		return "Son say hi";
	}

	String name() {

		return "name is Son";
	}
}

class Differ {

	public static void main(String args[]) {
		Father s = new Son();
		System.out.println(s.sayHi() + "----" + s.name());
	}

}

输出结果为:

Father say hi----name is Son

结果分析:因为子类继承了静态方法sayHi(),但并没有动态绑定到Son对象上因此,Son对象的sayHi()方法并没有复写父类的该方法。因此打印的结果为Father say hi。
十 继承:

1 继承的好处:
    1) 提高了代码的复用性
    2) 让类与类之间产生了关系。有这个关系,才有了多态的特性。
       注意:不能为了获取其他类的方法,简化代码而继承。

    3) java不支持多继承。
    原因:多继承容易带来安全隐患:当多个父类中定义了相同的功能,当功能内容不同时子类对象不确定要运行哪一个(致命方块)。但是java保留这种机制。并用另一种体现形式来完全表现。多实现。
    4) 子类出现后,类成员的特点:
    变量
    如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this。子类要访问父类中的同名变量时 用super。
    super的使用和this的使用几乎一致。
    this代表的是本类对象的引用
    super代表的是父类对象的引用
    子父类中的函数
    当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。
    这种情况是函数的另一种特性:重写(覆盖)
    当子类继承父类,沿袭了父类的功能到子类中,但子类虽具备该功能,但功能的内容却和父类不一致。这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。    
    提示:1.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖否则编译失败。
          2.静态只能覆盖静态。静态不能覆盖非静态。
          3.重载和重写的区别:重载:只看同名函数的参数列表, 重写:字父类方法一模一样。(子类的返回类型可与父类有一定关系)。                             
    子父类中的构造函数
    在对子类进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句:super(); super():会访问父类中空参数的构造函数。而且子类中的所有构造函数默认第一行是super();
    问:为什么子类一定要访问父类中的构造函数。
    答:因为父类的数据子类可以直接获取。所以建立时,需要先查看父类但是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中 的构造函数。如果要访问父类中指定的构造函数,可以通过动定义super语句的方式指定。
    注意:super语句一定定义在子类构造函数的第一行,构造函数内要么有this()要么有super()两者只能择其一。
    结论:子类的所有构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式语句super();当父类中没有空参数构造函数时,子类必须通过super或者this语句形式来指定要访问的构造函数。当然子类的构造函数第一行也可以收到指定this语句来访问本类中的构造函数,子类中至少有一个构造函数会访问父类中的构造函数。     

     提示:抽象函数中也有构造方法但不能被实例化,子类的构造函数会调用抽象父类的构造函数。并且java中子类不不继承父类的构造函数的。   

2 final特点:

1)这个关键字是一个修饰符,可以修饰类,方法,变量。

2)被final修饰的类是一个最终类,不可以被继承。

3)被final修饰的方法是一个最终方法,不可以被覆盖。

4)被final修饰的变量是一个常量,只能赋值一次。

3 抽象类
     当多个类出现相同功能,但是功能主体不同,这时可以进行向上抽取功能定义,而不抽取功能主体。                                        
   抽象类的特点:

    1)抽象方法一定在抽象类中,抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。

    2)抽象方法只定义方法声明,并不定义方法实现。

    3)抽象类不可以被创建对象(实例化),因为调用抽象方法没有意义。

    4)抽象类中的抽象方法要被使用,必须用子类复写所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分方法,那么该子类好是一个抽象类。 

    5)抽象类只能单继承。

   抽象类的细节:

1)问:抽象类中是否有构造函数?答:有,用于给子类对象进行初始化。

2)问:抽象类中是否可以定义非抽象方法?答:可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。

3)抽象关键字abstract和哪些不可以共存?final , private , static 

4)抽象类中可不可以不定义抽象方法?可以。抽象方法目的仅仅为了不让该类创建对象。

4 接口

    1) 接口:初期理解,可以认为是一个特殊的抽象类。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式表示。class定义类,interfce用于定义接口。接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的对象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类。接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。接口和接口间可以继承,并支持多继承。
    2) 接口定义时,格式特点:             
     接口中的常见定义:常量,抽象方法。
     接口中的成员都有固定修饰符:
     常量:public static final
     方法:public abstract
    3) 接口的特点:
     接口是对外暴露规则
     接口是程序的功能扩展
     接口可以用来多实现
     类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
     接口与接口之间可以有继承关系
下面是一个模拟计算机主板运行与声卡网卡之间的关系,体现了接口提高了功能扩展,降低了耦合性的代码:  
                    
public interface PCI {
	public void open();

	public void close();
}

class MainBoard {
	public void run() {
		System.out.println("mainboard run");

	}

	public void usePCI(PCI p) {
		if (p != null) {
			p.close();
			p.open();

		}

	}

}

class NetCard implements PCI {

	@Override
	public void open() {
		// TODO Auto-generated method stub
		System.out.println("netcard open");
	}

	@Override
	public void close() {
		// TODO Auto-generated method stub
		System.out.println("netcaed close");
	}

}

class SoundCard implements PCI {

	@Override
	public void open() {
		// TODO Auto-generated method stub
		System.out.println("SoundCard open");
	}

	@Override
	public void close() {
		// TODO Auto-generated method stub
		System.out.println("SoundCard close");
	}

}

class DuoTaiDemo {

	public static void main(String args[]) {

		MainBoard mb = new MainBoard();
		mb.run();
		mb.usePCI(new NetCard());
		mb.usePCI(new SoundCard());
	}

}

打印结果为:

mainboard run
netcaed close
netcard open
SoundCard close
SoundCard open

4) 抽象类和接口的区别:

(1) 抽象类只能被继承,而且只能单继承。

    接口需要被实现,而且可以多实现。 

(2) 抽象类中可以定义非抽象方法,子类可以直接继承使用。

    接口中都有抽象方法,需要子类去实现。

(3) 抽象类使用的是is a 关系。

    接口使用的is like a 关系。

    我的理解:is a和is like a都是用于继承,区分的关键在于是否实现了新的接口,比如A继承B,但是A只是覆盖了B的方法,则称A is a B;如果A中新增了方法,则称A is like a B. 

(4) 抽象类的成员修饰符可以自定义。

    接口中的成员修饰符是固定的。全都是public的。

十二.内部类

1 内部类的访问规则
    1) 内部类可以直接访问外部类的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用。格式:外部类.this
    2) 外部类要访问内部类,必须建立内部类对象,访问格式:当内部类定义在外部的成员位置上,而且非私有,可以在外部其他类中可以直接建立内部类对象。格式:外部类名。内部类名 变量名=外部类对象.内部类对象;
    3) 当内部类在成员位置上,就可以被成员修饰符所修饰。比如,private::将内部类在外部类中进行封装;static:内部类就具备static特性。当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
    4) 在外部其他类中,如何直接访问static内部类的非静态成员: new Outer.Inner().function();
    5) 在外部其他类中,如何直接访问static内部类的静态成员:Outer.Inner().funtion();
    提示:当内部类中定义了静态成员,该内部类必须是static的。当外部类中的静态方法访问内部类时,内部类也必须是static的。
2 内部类定义在局部时:
    1)不可以被成员修饰符修饰(static.....)
    2)可以直接访问外部类中的成员,因为还持有外部类的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。(局部变量的生命周期比内部类短因此加final可延长其生命周期) 可参考以下代码:  
  
class Outer {

	int x = 3;

	void method(final int a) {
		final int y = 4;
		class Inner {
			void function() {

				System.out.println(a);

			}

		}
		new Inner().function();

	}

}

class InnerClassDemo {
	public static void main(String args[]) {
		Outer out = new Outer();
		out.method(6);
		out.method(7);

	}

}
打印结果为:
6
7

3 匿名内部类:

    1)匿名内部类:没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。
    2)定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
    3)匿名内部类的格式:new 父类或者接口(){  //定义子类成员或者覆盖父类方法  }
    4)其实匿名内部类是一个匿名子类对象。而且这个对象有点”胖“。可以理解为带内容的对象。
    5)匿名内部类中定义的方法最好不超过3个。
      匿名对象使用方式一:当对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。如果对一个对象进行多个成员调用,必须给这个对象起个名字。
      匿名对象使用方式二:可以将匿名对象作为实际参数进行传递。
当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。 其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。







                       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值