数组是程序设计中提供的一种重要的数据类型,在java中属于引用数据类型,涉及到堆栈空间分配和引用传递的问题。
数组时基础的线性存储结构,可以有效实现一组变量的关联。
声明并开辟数组
数据类型 数组名称 [] = new 数据类型 [长度] ;
数据类型 [] 数组名称 = new 数据类型 [长度] ;
数组下标从0开始,如果访问超过数组允许的下标长度,会出现数组越界异常
数组名称.length 属性,直接获取数组长度
int data []=new int [3]; System.out.print(data.length);
数组属于引用数据类型,需要进行内存分配。数组与对象保存的唯一区别:对象中的堆内存保存的是属性,数组中的堆内存保存的是一组信息。
数组本身分为动态初始化和静态初始化,动态初始化后的数组每个元素的内容都是对应数据类型的默认值,随后通过下标为数组设置内容。
如果定义数组的时候设置内容,可以采用静态初始化方式。
int data[] = new int[]{11,22,33};
数组使用需要通过关键字new开辟堆内存空间,一块堆内存空间可以同时被多个栈内存指向,进行引用数据操作。不能直接使用未开辟空间的数组,不然会出现空指向异常。
为了简化数组与集合数据的输出问题,可以使用foreach结构,不仅简化for循环的定义结构,也可以避免数组越界异常。
for(数据类型 变量:数组|集合){ }
for(int temp:data){ System.out.print(temp+”、”); }
二维数组
动态初始化:数据类型 数组名称[][]=new 数据类型[行数][列数];
静态初始化:数据类型 数组名你[][]=new 数据类型[][]{{值,值,值},{值,值,值}};
for(int temp[]:data){
for(int num:temp){
System.out.print(num+”、”);
}
System.out.println();
}
数组进行引用传递处理中,最常见的就是基于方法进行引用传递的处理或返回。
数组可以保存多个数据内容,可以对数组数据进行排序操作并保存。
class ArrayUtil{
public static void sort(int data[]){…}
public static void ArrayUtil(int temp[]){…}
}
使用static方法,由于ArrayUtil类没有提供任何成员属性定义,即便产生ArrayUtil实例化对象也没有意义。
程序定义的ArrayUtil类使用static方法,在没有实例化对象时已经调用执行方法了,减少无用对象产生。
JDK中支持数据排序和数组复制操作:
数组排序:
int data[] = new int[]{1,3,2,5,4};
java.util.Arrays.sort(data);
数组复制:System.arraycopy(源数组名称,源数组开始点下标,目标数组名称,目标数组开始点下标,复制长度)
int dataA[]=new int[]{1,2,3,4,5,6,7,8,9};
int dataB[]=new int[]{11,22,33,44,55,66,77,88,99};
System.arraycopy(dataA,5,dataB,3,3);
输出dataB:11,22,33,6,7,8,77,88,99
为了避免方法中参数的执行限制,Java提供了方法可变参数的支持,可以在方法调用时采用动态形式传递若干个参数数据,可变参数定义:
public [static][final] 返回值类型 方法名称(参数类型… 变量){
[return [返回值];]
}
public static int sum(int… data){ }
如果方法需要接收普通参数和可变参数,可变参数要定义在最后,并且一个参数只允许定义一个可变参数。
public static void sum(String name, String url, int… data){ }
调用本方法时,前面两个参数必须传递,可变参数根据需求传递
Java的所有数据类型都可以定义数组,除了基本数据类型的数据可以定义数据,引用数据类型也可以定义数组,这样的数组为对象数组:
对象数组动态初始化: 类 对象数组名称[]=new 类[长度];
对象数组静态初始化: 类 对象数组名称[]=new 类[]{实例化对象,实例化对象,…};
Person per[] =new Person[3];
Person per[] =new Person[]{new Person(“张三”,20),new Person(“李四”,30)};
合成设计模式:通过不同的类实现子结构定义,随后将其在一个父结构中整合。
数据表与简单Java类映射转换:
7、String类数据实体表设计 = 类的定义
表中的字段 = 类的成员属性
表的外键关联 = 对象引用关联
表的一行记录 = 类的一个实例化对象
表的多行记录 = 对象数组
项目开发中,String是一个必须使用的程序类,是项目的核心组成类,所有字符串使用“””定义,使用“+”实现字符串的连接
String本身属于一个系统类,可以直接赋值的形式进行对象实例化,也提供相应的构造方法进行对象实例化。构造方法:
public String(String str)
字符串比较通过“==”关系运算符来判断,在String对象上表示的是内存地址数值的比较,结果为false或true
对于同一字符串采用不同方法进行String类对象实例化,并不是所有String类对象的地址数值都是相同的。
对于字符串内容的判断,使用equals()方法:strA.equals(strB);
常量是不会被修改的内容,使用““”定义的字符串常量,严格来讲是String类的匿名对象(没有指向)
String str=“csdn”;
类的普通方法只有通过实例化对象才可以调用,表示字符串常量就是String类的匿名对象,String类对象直接赋值操作,就是将一个匿名对象设置了一个名字。但是String类的匿名对象是由系统自动生成的,不再由用户自己创建。
在JVM底层存在一个对象池,当代码中直接赋值定义了一个String类对象时,会将该字符串对象所使用的匿名对象入池保存,如果后续还有其他String类对象也采用了直接复制的方式并设置了同样内容,则不会再开辟新的堆内存空间,而是将使用已有的对象进行引用的分配。
使用String类的构造方法实例化对象,使用构造方法定义新的内存空间,不会自动入池,使用intern()方法手动保存到对象池。
String strA=new String(“csdn”).intern(); String strB=”csdn”; System.out.print(strA==strB);//true
直接赋值 String str=”abc”;只开辟一块堆内存空间,并且会自动保存在对象池中以供重复使用。
构造方法 String str=new String(“abc”);会开辟两块堆内存空间,有一块成为垃圾,并且不会自动入池,可以使用intern()方法手动入池。
字符串常量池:为了防止多个内容相同的实例化对象重复开辟堆内存空间,JVM中提供了一个字符串常量池(本质是一个动态对象数组),所有通过直接赋值实例化的String类对象都自动保存在常量池中。
Java的字符串常量池包括:
静态常量池(程序*.class加载时紫红将此程序保存的字符串、普通常量、类、方法信息进行分配)
运行时常量池(一个程序*.class加载后,一些字符串内容通过String对象的形式保存后实现字符串连接处理)。
字符串方法
public char charAt(int index) 获取指定索引位置的字符 public char[] toCharArray() 将字符串中的数据以字符数组的形式返回 char c=str.charAt(6); char[] result=str.toCharArray();
Java开发中,返回boolean值的方法习惯以isXxx()形式命名
String类提供了将字符串转变为字节数组的操作,为了方便数据传输和编码转换。
public byte[] getBytes() 将字符串转为字节数组 byte data[]=str.getBytes();
字符串比较:
public boolean equals(String anObject) 区分大小写的相等判断 public boolean equalsIgnoreCase(String anotherString) 不区分大小写比较 public int compareTo(String anotherString) 判断两个字符串大小(按照字符编码比较) public int compareToIgnoreCase(String str) 不区分大小写的字符串比较
字符串查找:
str.contains(“hello”);子字符串hello是否存在在str中 str.indexOf(“hello”); 查找指定字符串的位置,找到返回起始索引,找不到返回-1 str.lastIndexOf(“.”);从后向前查找字符串,返回第一个查找到的索引位置 str.startsWith(“**”);判断是否以指定的字符串开头 str.startsWith(“@@”,2);判断指定索引之后进行开头判断 str.endsWith(“##”); 判断是否以指定的字符串结尾
字符串替换:
str.replaceAll(“w”,“-”);全部替换 str.replaceFirst(“w”,“-”);替换首个
字符串拆分:
String result[]=str.split(“ ”); 空格拆分 如果spilt()方法的参数为空字符串则表示根据每个字符拆分 String result[]=str.split(“ ”,2);拆分为指定长度的数组(2个) String str=”192.168.1.3”; String result[]=str.split(\.);
字符串以.拆分,需要对.进行转义,使用(表示一个)
字符串截取:
str.substring(4);从指定位置索引截取到结尾 str.substring(4,8);截取指定索引范围内的子字符串
字符串格式化:
利用占位符实现数据的输出,常用到占位符有字符串(%s)、字符(%c)、整数(%d)、小数(%f)
String str=String.format(“姓名:%s、年龄:%d、成绩:%5.2f”,name,age,score); str.length() 字符串长度 str.trim() 去掉前后空格 str.toUpperCase() 转大写 str.toLowerCase() 转小写8、继承
面向对象程序设计主要优点时代码的模块化设计以及代码重用,继承可以实现类的可重用性定义。
利用继承性可以实现类结构的重用定义,继承性是指扩充一个类已有的功能
class 子类 extends 父类{ }
继承结构中,子类称为派生类,父类成为超类
class Student extends Person{ }
继承结构中,子类需要重用父类中的结构,在进行子类对象实例化之前往往都会默认调用父类中的无参构造方法,为父类对象实例化,然后进行子类构造调用,为子类对象实例化。子类对象实例化之前一定会实例化父类对象,实际上相当于子类的构造方法里面隐含了一个**super()**的形式。
如果父类没有提供无参构造方法时,可以通过super(参数,…)调用指定参数的构造方法。对于super()构造的调用语句只能在子类的构造方法中定义,并且必须放在子类构造方法的首行。
一个子类只能继承一个父类,存在单继承局限。
class A{}
class B extends A{ }
class C extends B{ }
为多层继承,Java只允许多层继承,不允许多重继承 class C extends A,B{ }
一个子类继承时,会继承父类的所有操作(属性、方法),对于所有非私有的(no private)操作属于显式继承(可以直接利用对象操作),所有私有(private)操作属于隐式继承(间接访问,例如:getter()方法)。
由于某些需要,子类可能会定义与父类名称相同的方法或属性,这种情况在面向对象设计中称为覆写。子类定义与父类中方法名称、返回值类型、参数类型、个数完全相同的方法。
如果需要子类调用父类已被覆写过的方法:
在子类方法中首行添加 super.父类方法名称();
this调用结构时会先从本类查找,没有则去寻找父类中的相应结构,而super调用时不会查找子类,直接调用父类。
被子类所覆写的方法不能拥有比父类更严格的访问控制权限,
目前接触到的3种访问控制权限大小关系:private
如果父类中的方法时default,那么子类覆写只能是default或public,如果父类方法时public,子类只能是public。private权限声明的方法无法被子类覆写。
构造方法不能被继承,因此不能被覆写,可以被重载。
子类可以对父类的方法进行覆写,也可以对非private定义的父类属性进行覆盖,只需定义与父类成员属性一致的名称。
父类info成员属性:super.info() 子类info成员属性:this.info()
final在程序中描述为终接器的概念,可以实现定义不能被继承的类,定义不能被覆写的方法,定义常量(全局常量)
使用final定义的类不能有子类
final class Channel(){ }
使用final定义的方法不能被子类覆写
public final void connect(){ }
使用final定义常量,常量的内容一旦定义则不可修改
private final int ON=1;
private final int OFF=0;
定义全局常量
public static final int ON=1;
public static filan int OFF=0;
static主要功能时进行公共数据的定义,同时使用final表示定义的常量为公共常量。
Annotation注解,Annotation通过注解配置简化程序配置代码的一种技术手段。
程序开发的3个过程:
(1) 程序定义的时候将所有可能使用到的资源全部定义在程序代码中
(2) 引入配置文件,在配置文件中定义要使用的服务器资源
(3) 将配置信息重新写回程序里面,用一些特殊标记将配置信息与程序代码进行分离,就是注解的作用。
现在开发基本上采用配置文件+注解的形式完成。
3个基础Annotation注解:@Override、@Deprecated、@SuppressWarnings
准确覆写:在子类中明确描述某些方法时覆写来的,利用@Override注解标注。
@Override
public void connect(){ }
过期声明:程序开发需要不断进行更新迭代,会出现一些不再推荐使用的结构,过期操作用@Deprecated注解。
@Deprecated //过期操作:不建议使用
public void connect(){ }//该操作在其他子系统可能会继续使用,所以不能删除
压制警告:为了代码的严格性,在编译的时候有时会给出一些错误的提示信息,但是有些错误提示信息并不是必要的,为了防止这些提示信息的出现,使用@SuppressWarnings注解进行警告信息的压制。
使用value属性设置压制的警告类型:
deprecation使用了不赞成使用的类或方法时的警告
@SuppressWarnings(value={“deprecation”})
public static void main(String args[]){
new Channel().connect();//警告信息将被压制
}
面向对象多态性,面向设计中的多态性描述是同一结构在执行时会根据不同的形式展现出不同的效果。
方法的多态性:
方法的重载:同一方法可以根据传入的参数类型或个数不同实现不同功能。
方法的覆写:同一方法可能根据实现子类的不同有不同的实现。
对象的多态性(父类与子类实例之间的转换处理): 对象向上转型:父类 父类实例=子类实例,自动完成转换。
Message msg=new DatabaseMessage(); msg.print();//所调用的方法为被实例化子类所覆写过的方法 对象向上转型特点在于可以通过父类对象自动接收子类实例。利用这一原则可以实现方法接收或返回参数类型的统一。 Channel.send(new DatabaseMessage());//子类实例 Channel.send(new NetMessage());//子类实例
对象向下转型:子类 子类实例=(子类) 父类实例,强制完成转换。 如果子类已经发生了向上转型后需要通过强制性向下转型实现子类扩充方法调用。
Person per=new Superman();//向上转型 per.run();//父类方法 Superman spm=(Superman) per;//强制转为子类实例 spm.fly();//子类扩充方法 spm.fire();//子类扩充方法
必须要先发生向上转型,才能进行向下转型
为了保证向下转型的安全性,Java提供了instanceof关键字,在转换前通过进行对象所属类型的判断:
对象 instanceof 类
返回boolean类型数据,如果是true表示实例是指定类对象。
为了方便操作类型的统一,也为了方便每个类定义的一些公共操作,设计了一个公共的Object父类,是所有类的父类。
class Person{ } 与 class Person extends Object{ }效果相同。
所有类的对象都可以利用向上转型的特点为Object类对象实例化。
Object obj = new Person();//向上转型
if(obj instance Person){//实例判断 obj属于Object和Person类
Person per =(Person) obj;//向下转型,可以调用子类扩充方法
}
当某些操作方法需要接收任意类型时,最合适的参数类型就是Object
Object类中提供了一个toString()方法,可以实现对象信息的获取,该方法时在直接进行对象输出时默认被调用的。
@Override
public String toString(){ }//覆写父类Object的toString()方法
对象比较:Object类的equals()方法中两个对象的比较时基于地址数值判断实现的,如果子类有对象比较的需求,可以覆写该方法。
9、抽象类与接口利用抽象类和接口可以有效拆分大型系统,避免产生耦合问题。
类继承的主要作用是扩充已有类的功能,子类可以根据自己的需要选择是都要覆写父类中的方法,一个设计完善的父类是无法对子类做出任何强制性的覆写。抽象类增加了抽象方法的定义,可以在使用时要求必须被子类所继承,并且子类必须覆写全部抽象方法。
抽象类最大的特点是必须有子类,并且无法直接进行对象实例化操作。开发中,很少回去继承设计完善的类,大多都会考虑继承抽象类。
抽象类是为方法覆写提供的类结构,使用abstract class定义,一个抽象类中可以利用abstract关键字定义若干个抽象方法,这样抽象类的子类必须在继承抽象类时强制覆写全部抽象方法。
abstract class Message{//抽象类
public abstract String getConnectInfo();//抽象方法,不需要定义方法体{}
}
抽象类的对象实例化可以利用对象多态性通过子类向上转型的方式完成
Message msg=new DatabaseMessage();
(1) 抽象类必须有子类继承,所以定义时不允许使用final关键字定义抽象类或抽象方法
(2) 抽象类中可以定义成员属性与普通方法,为了可以为抽象类中的成员属性初始化,可以在抽象类中提供构造方法。子类在继承抽象类时会默认调用父类的无参构造方法,如果抽象类没有无参构造方法,子类需要使用super()形式调用指定参数的构造方法。
(3) 抽象类中允许没有抽象方法,可以也无法直接用关键字new直接实例化抽象类对象。
(4) 抽象类可以提供static方法,并且该方法不受抽象类实例化对象的限制。
类的作用主要是可以对一类事物的共性特征进行抽象,从设计层次来讲,抽象类的设计比普通类的级别更高,抽象类是在类级别的进一步抽象。
为了统一参数传输类型,需要针对基本数据类型实现引用传递,Java提供了包装类。
基本数据类型进行包装处理后可以像对象一样进行引用传递,同时也可以使用Object类进行接收。Java专门设计了8个包装类:byte(Byte)、short(Short)、int(Integer)、long(Long)、float(Float)、double(Double)、boolean(Boolean)、char(Character)
对于包装类可以分为以下两种类型:
对象型包装类(Object直接子类):Boolean、Character
数值型包装类(Number直接子类):Byte、Short、Integer、Long、Float、Double
基本数据类型的包装类是为了基本数据类型转换为对象引用而提供的。
数据装箱:将基本数据类型保存到包装类中;
数据拆箱:从包装类中获取基本数据类型。
Integer obj new Integer(10);//装箱 int num=obj.intValue();//拆箱 System.out.print(num*num);//数值计算
数据类型转换:
parseInt(String s) Integer类 parseDouble(String s) Double类 parseBoolean(String s) Boolean类 int num=Integer.parseInt(str);
通过基本数据类型包装类可以实现String与基本数据类型之间的转换,如果想将基本数据类型转变为String类对象的形式可以使用以下方法。
(1)连接空字符串 String str=num+””;
(2)使用valueOf()方法转换 String str=String.valueOf(num);//字符串转换
接口:Java中接口属于一种特殊的类,主要特点是用于定义开发标准。需要通过interface关键字定义,接口中可以定义全局常量、抽象方法、default方法、static方法。
接口需要被子类实现,子类利用implements关键字可以实现多个父接口;
子类如果不是抽象类,一定要覆写接口中所有的抽象方法; 接口对象可以使用子类对象的向上转型进行实例化。
IMessage msg=new MessageImpl();
子类可以继承父类也可以实现父接口:
class 子类 [extends 父类] [implements 接口1,接口2,…]{ }
抽象类可以实现一些公共方法的定义,可以利用extends先继承父类再利用implements实现若干父接口顺序完成子类的定义。
class MessageImpl extends DatabaseAbstract implements Imessage, Ichannel{}
extends 在类上只能继承一个父类,在接口上可以继承多个
接口最初的组成是抽象方法与全局常量,还可以使用default定义普通方法或使用static定义静态方法。
设计接口主要功能是进行公共标准的定义,定义普通方法便于扩充接口功能,同时简化设计结构。使用default定义的普通方法需要通过接口实例化对象才可以调用,为了避免实例化对象的依赖,在接口中可以使用static定义方法。
对接口而言,开发中最重要的应用就是进行标准的制定。项目开发中要考虑类实例化对象的解耦和问题,通过工厂设计模式隐藏接口对象实例化操作细节。
主类(客户端)–只关注标准(接口)不关注子类
接口—操作标准
接口子类—覆写方法
类—实例化接口对象,隐藏子类信息
代理设计模式:实现核心业务与辅助功能的细分
主类(客户端)
核心接口—核心业务标准
核心业务实现类—真实主题类 代理业务类—代理主题类
主类—获取代理对象,同时传入被代理者;
调用代理方法
使用泛型可以避免对象强制转型带来的安全隐患问题,泛型可以在编译时检测出程序的安全隐患,使程序更加健壮。类中的属性或方法的参数与返回值的类型采用动态标记,在对象实例化的时候动态配置要使用的数据类型。
泛型在类上标记后,需要通过实例化对象进行类型的设置,设置的类型只能是引用数据类型。如果要设置基本数据类型,需要采用包装类的形式。
Class Point{//坐标点,T属于类型标记,可以设置多个标记 Private T x; Private T y; //setter、getter省略 } //实例化Point类对象,设置泛型标记T的目标数据类型,属性、方法参数、返回值的类型动态配置 Point point=new Point (); //内容设置,所有数据通过Object接收 point.setX(10);//自动装箱 point.setY(20);//自动装箱 //从里边获取数据,由于返回的是Object类型,需要进行强制性向下转型 int x=point,getX();//避免强制转型 int y=point.getY();//避免强制转型
利用泛型类在实例化对象时进行的动态类型匹配,在程序中实例化泛型类对象时,不同泛型类型的对象之间彼此无法进行引用传递。
10、类结构扩展Java中,包主要目的时将不同功能的文件进行分割,在Java中使用package定义包名称,写在源代码首行。
定义包 package cn.demo;//使用public class定义类 导入包 import cn.demo;//导入其他包的类 import 包.*的导入模式不影响程序性能
如果定义的方法都是static型,使用静态导入import static 包.类.*
静态导入的优点时,不同类的静态方法好像在主类中定义一样,不需要类名称就可以直接调用。
jar是一种Java给出的压缩格式文件,可以将*.class文件以*.jar压缩包的形式给用户,方便程序的维护。
定义一个类,随后将其打包成jar包文件: 对程序打包编译:javac -d 程序.java
形成cn的包,有相应的子包和*.class文件,打包成mldn.jar: jar -cvf mldn.jar cn
每个*.jar文件都是一个独立的程序路径,如果想在Java程序使用此路径,需要通过CLASSPATH进行配置: SET CLASSPATH=.;d:mldn.jar
protected权限:允许本包以及不同包的子类进行访问 属性声明以private为主,方法声明以public为主
在类结构中每当使用关键词new都会调用构造方法并进行实例化新的对象,可以利用构造方法的私有化形式实现实例化对象的控制。
单例设计模式:整个系统中一个类只允许提供一个实例化对象,可以通过private进行构造方法的封装,这样该类就无法再类的外部利用关键词new实例化新的对象。
//在类内部进行Singleton类对象实例化,为了防止可能出现重复实例化,使用final标记
class Singleton{
private static final Singleton INSTANCE new Singleton();
//构造方法私有化,外部无法通过关键词new实例化
private Singleton(){ }
//外部不管有多少个Singleton类对象,实质上最终都只调用唯一的Singleton类实例
…
}
多例设计模式:在单例设计模式基础上进一步扩展可以实现有限个实例化对象的定义。例如定义一个表示星期几的操作类,这个类对象有7个实例化对象(星期一到星期日),这样的类不应该由用户无限制的创造实例化对象,应该只使用有限的几个,就是多例设计模式。
class Color{
private static final Color RED=new Color(“红色”);
private static final Color GREEN=new Color(“绿色”);
private static final Color BULE=new Color(“蓝色”);
private String title;
private Color(String title){
this.title=title;
}}
枚举:enum定义枚举类型,简化多例设计模式的定义。
enum Color{RED,GREEN,BLUE;}
//Color类的3个实例化对象,在外部调用可以直接利用枚举名称进行对象的调用。
所有枚举类的对象名称全部采用大写字母定义,也可以采用中文定义。
enum Color{ RED,GREEN,BLUE;}
//输出枚举中的全部内容
for (Color c: Color.values()){ System.out.print (c+“、”); }
//c.ordinal()获得对象名字,c.name()获得对象序号
在枚举类中可以定义若干个实例化对象,也可以像普通类那样定义成员属性、构造方法、普通方法。枚举类本质上属于多例设计模式,构造方法不允许使用public定义。如果类中没有提供无参构造方法,则需要定义每个枚举对象时明确传入参数内容。
RED(“红色”),GREEN(“绿色”),BLUE(“蓝色“);



