Java 总结
Java 总结
第一部分:知识复习要点
-
Java技术体系分成哪三大部分?JAVAEE(企业级计算)、JAVASE(桌面级计算)、JAVAME(移动计算)
-
JDK中:
- 用于编译Java源程序的命令是:
javac 源程序名.java
- 用于运行Java程序的命令是,
java 程序名
- 键盘标准输入流的对应的对象是:
System.in
对象 - 屏幕标准输出流对应的对象是:
System.out
对象
- 用于编译Java源程序的命令是:
-
PATH环境变量的作用?
环境变量主要作用是找到程序的安装路径。我们用windows的命令行执行命令的时候,是需要到相应程序的安装路径下面去执行的。
-
JAVA中各个基本数据类型的大小(即在内存中占用的字节数。如:int 大小是4个字节等... )
-
如何定义一个全局型的常量?
//定义全局型的一个PI常量。 public static final double PI=3.14159d;
-
JAVA中汉字的范围(用于判别汉字):\U4e00-\U9fa5
-
定义一个类,用于表达:二维坐标平面上面的点。或定义一个类,用于表达:复数?或定义一个类,用于表达表达:圆?能写出代码。
-
能简述 static 数据成员 与非static 数据成员的区别、用法。
静态变量和实例变量的区别如下:
-
静态变量在内存中占用一份拷贝,运行时Java虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存空间分配。可以直接通过类名访问静态变量。
-
对于实例变量,每创建一个实例,就会为实例变量分配一次内存。实例变量可以在内存中有多份拷贝,互不影响。
静态方法:
-
在静态方法里只能直接访问类中其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例后才可使用。而非静态方法属于对象的具体实例,只有在类的对象创建时在对象的内存中才有这个方法的代码段。
-
静态方法不能以任何方式引用this和super关键字。因为静态方法在使用前是不需要创建任何对象的,当静态方法被调用时,this所引用的对象根本就没有产生。
-
子类只能继承、重载、隐藏父类的静态方法,子类不能重写父类的静态方法,也不能把父类不是静态的方法重写成静态的方法。
-
-
能简述:四种访问控制符(publuc 、protected、缺省、private)各自的含义。
-
能定义一个抽象类。能写出代码片断。
-
能定义一个接口。能写出代码片断。
-
外部类、内部类的概念及相应知识点。能据此知识点:阅读程序,写出运行结果。
-
类和对象的初始化顺序方面相应知识点(含:对象初始化块、类初始化块)。能据此知识点:阅读程序,写出运行结果。
所有类的初始化块(父类的类的初始化块 --> 子类的类的初始化块) --->> 所有对象的初始化块-->构造器
-
try-catch-finally语句的语句。
-
throws子句与throw语句的含义与区别
-
throw语句是抛出一个异常。throws语句是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
-
throws出现在方法函数头;而throw出现在函数体。
-
throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常。
-
-
try-catch-finally语句中包含return语句时的处理。能据此知识点:阅读程序,写出运行结果。
-
根据你的理解:回答JAVA中的继承机制。
继承机制主要具有双重作用:一是作为类的构造机制,二是作为类型的构造机制。
作为类的构造机制,继承通过扩充、组合现有的类来构造新的类。扩充是指形成现有类的特例——派生类,组合是指抽取出若干现有类的共性形成新的抽象层次——基类。
作为类型的构造机制,如果子类继承父类,则所有要求对象为父类类型的地方也可以接受子类类型的对象。也就是说父类对象出现的地方可以用子类对象替代。也就是里氏替换原则。- 子类拥有父类非private的属性,方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法(重定义)。
- java的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这
- java继承区别于C++继承的一个特性。但接口允许多继承。
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
-
理解JAVA中继承、方法重载、方法重写、方法隐藏的知识点,能据此知识点:阅读程序,写出运行结果。
隐藏和覆盖的区别:
被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性
被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法
因为覆盖是动态绑定,是受RTTI(run time type identification,运行时类型检查)约束的,隐藏不受RTTI约束,总结为RTTI只针对覆盖,不针对隐藏
区别 覆盖 重载 实现 子类对父类方法的重写 同一个类中建立多个同名方法 参数 与父类同名同参 与别的方法同名不同参 返回 子类与父类返回类型要一致 权限 子类不能覆盖父类的private方法 父类一个方法只能在子类覆盖一次 重载只要参数不同,可以多次 覆盖是针对父类方法的重写 同类中的方法均可重载 重写要求父类鼻子类抛出更少的异常
第二部分:示例代码
输出字符'啊'的UNICODE码值
public static void main(String[] args) {
System.out.println("字符'啊'的UNICODE码值:"+(int)'啊');
}
//21834
对给定的年份如: int year=1986;输出是不是一个闰年。
public static void main(String[] args) {
// TODO Auto-generated method stub
int year=1986;
boolean isLeap=false;
isLeap = (year % 400 == 0)||(year % 4 == 0 && year % 100 != 0);
System.out.println("1986年="+isLeap);
}
给定四个字节b1,b2,b3,b4,拼接成一个int 整数值,其中:b1在最左边,b4在最右边,按b1b2b3b4次序拼接。
byte b1 = (byte)(0xaa), b2 = (byte)(0xbb), b3 = (byte)(0xcc), b4 = (byte))0xdd;
int i = b1 << 24 | (b2 << 16) & 0x00ff0000 | (b3 << 8) & 0x0000ff00 | b4 & 0x000000ff;
定义一个类,表达:二维 坐标平面上的点:
public class Point {
private int x,y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point(int x) {
this(x,0);
}
public Point() {
this(0);
}
//此处可添加其它所需要的方法
//.......
@Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
}
类与对象的初始化块、初始化次序相关知识点。
自定义异常。
public class KBException extends IOException{
String str;
MyException1(String _str) {
this.str = _str;
}
public String toString() {
sout(str);
}
}
public class KBPress{
public static int read() throws KBException{
//throws是声明异常。
int ch;
try{
ch = System.in.read();
if(ch == 'A'){
throw new KBException ("A键已坏");
}
}
catch(IOException e){
throw new KBException(e.getMessage());
//throw是抛出异常。
}
return ch;
}
}
public class Client{
public static String[] main(String[] args){
int ch;
try{
while((ch = KBPress.read()) != -1){
sout("" + ch);
}
}catch(KBException e){
sout("" + e.getMessage());
}
}
}
try与return 语句 下列方法运行的结果是:
int f(int x){
try {
if(x>0) throw new Exception("x>0");
return 1;
}catch(Exception e) {
return 2;
}finally {
return 3;
}
}
/*
问:f(-1)时方法的返回值是多少?
f(1)时方法的返回值又是多少?
答:都是3
*/
抽象类:设计一个类,能对任何 的几何图形求面积.
//表达:任何几何图形--抽象概念 -->抽象类!
public abstract class Graphix {
public abstract double area(); //抽象方法!方法体不需要写!(无法写出!)
}
//定义一个通用的工具类:完成对任何几何图形求面积:
public class Tools {
public static double calArea(Graphix g) {
return g.area();
}
/**
* @param args
*/
public static void main(String[] args) {
Circle c=new Circle();
Tools.calArea(c);
Square s=new Square();
Tools.calArea(s);
}
}
public class Circle extends Graphix{
@Override
public double area() {
System.out.println("按圆面积公式求。");
return 0;
}
}
public class Square extends Graphix{
@Override
public double area() {
System.out.println("按正方形面积公式求。");
return 0;
}
}
输出前n个质数。
public class PrintPrimes {
public static boolean isPrime(int n)
{
for(int i=2;i*i<=n;i++)
{
if(n % i ==0 ) return false;
}
return true;
}
//输出前n个质数
public static void printPrimes(int n)
{
int cc=0;
for(int i=2;cc<n;i++)
{
if(isPrime(i))
{
System.out.print(" "+i);
cc++;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
printPrimes(20);
}
}
递归方式求前n个数的和,
public static int sum(int n)
{
return (n==1)?1:sum(n-1)+n;
}
递归方式把一个数n逆序输出。如:参数是1234,则返回4321
public static int reverse(int n)
{
return reverse(0,n);
}
private static int reverse(int m,int n)
{
return n==0?m:reverse(m*10+n%10,n/10);
}
使用ArrayList类,完成:将一个十进制安徽,转成二进制。
public static void conv(int n)
{
ArrayList<Integer> al=new ArrayList<Integer>();
do {
al.add(n%2);
n /= 2;
} while (n!=0);
for(int i=al.size()-1;i>=0;i--)
{
System.out.print(""+al.get(i));
}
}
使用HashMap类,完成:汉字串中每一个汉字出现的次数。
public static void count(String s)
{
if(s==null) return;
HashMap<Character, Integer> map=new HashMap<Character, Integer>();
for(int i=0;i<s.length();i++)
{
char c=s.charAt(i);
Integer freq=map.get(c);
map.put(c, (freq==null?1:freq+1));
}
System.out.println("统计结果:"+map);
}
字符串相等比较:
public class TestStr {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("男".compareTo("女"));
String s1="Hello";
String s2="Hello";
String s3=new String("Hello");
String s4=new String("Hello");
System.out.println("s1==s2?"+(s1==s2));
System.out.println("s3==s4?"+(s3==s4));
System.out.println("s1==s3?"+(s1==s3));
System.out.println("s1.equals(s2)?"+s1.equals(s2));
System.out.println("s3.equals(s4)?"+s3.equals(s4));
System.out.println("s1.equals(s3)?"+s1.equals(s3));
//结构分析初步!
System.out.println("Abtest.txt".startsWith("Ab"));
System.out.println("Abtest.txt".endsWith(".txt"));
}
}
将"aaaabbbbccccccdd";压缩成:"abcd"; 核心代码片断如下:
String s="aaaabbbbccccccdd";
System.out.println(s.replaceAll("(.)+\\1", "$1"));
字符串拆分:copy c:/a.txt d:/bb.txt
String s="copy c:/a.txt d:/bb.txt";
//起分隔作用的字符串是:空格串,即:\\s+
String[] ss=s.split("\\s+");
for(String e:ss)
{
System.out.println(es);
}
对字符串中"ABD237&&9309jf898icdm4390"中数值求和。
//方法一: 使用split()方法。
//代码片断:
String s="ABD237&&*9309jf898icdm4390";
//这分隔作用的是:非数字,即:[^0-9]+
String[] ss=s.split("[^0-9]+");
int sum=0;
for(String e:ss)
{
if(e.trim().length()>0)
{
int v=Integer.parseInt(e);//将整数值的串,变成整数值。
sum += v;
}
}
System.out.println("sum="+sum);
//方法二:使用Pattern类
Pattern p=Pattern.compile("\\d+");
Matcher m=p.matcher("ABD237&&*9309jf898icdm4390");
int sum=0;
while(m.find())
{
String e=m.group();
int cv=Integer.parseInt(e);
sum += e;
}
System.out.println("sum="+sum);
//方法三:使用Scanner类,最方便
Scanner sc=new Scanner("ABD237&&*9309jf898icdm4390");
//重要:分隔作用的是:非数字串,即: [^\\d]+
sc.useDelimiter("[^\\d]+");
int sum=0;
while(sc.hasNextInt())
{
sum += sc.nextInt();
}
System.out.println("sum="+sum);
模板串。
public class Ex2 {
public static String process(String tmp, String ds){
String res="";
HashMap<String, String> map=new HashMap<String, String>();
String[] r_ds=ds.split(",");
for(String e:r_ds)
{
if(e.length()>0)
{
String[] r_e=e.split(":",2);
map.put(r_e[0],r_e[1]);
}
}//for
Pattern p=Pattern.compile("\\$\\{(.+?)\\}");
Matcher m=p.matcher(tmp);
StringBuffer sb=new StringBuffer();
while(m.find())
{
m.appendReplacement(sb, map.get(m.group(1)));
}//while
m.appendTail(sb);
res=sb.toString();
return res;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.print("请输入模板串:");
Scanner sc=new Scanner(System.in);
String tmp=sc.nextLine();
System.out.print("请输入数据源串:");
String ds=sc.nextLine();
String res=process(tmp,ds);
System.out.println("处理结果:"+res);
}
}
分子量计算
public class TestREG {
private static HashMap<String, Float>map=new HashMap<String, Float>();
static {
/*
C, H, O, N,原子量分别
为12.01, 1.008, 16.00, 14.01
(单位:g/mol)。
*/
map.put("C",12.01f);
map.put("H",1.008f);
map.put("O",16.00f);
map.put("N",14.01f);
}
public static float cal(String s)
{
float s_w=0;
Pattern p=Pattern.compile("([CHON])(\\d*)");
Matcher m=p.matcher(s);
while (m.find()) {
String k=m.group(1);
String n=m.group(2);
float w=map.get(k);
int num=1;
if(n.length()>0)
{
num=Integer.parseInt(n);
}
s_w += w*num;
}//while
return s_w;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.print("请输入一个分子式:");
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();
if(s.matches("([CHON]\\d*)+"))
{
float w=cal(s);
System.out .println("分子式:"+s +"分子量是:"+w+"g/mol");
}
else {
System.out.println("分子式不对");
}
}
}
键盘上输入的任何内容,在屏幕上输出
public class Exp1 {
public static void main(String[] args)
throws Exception
{
int ch;
while((ch=System.in.read())!=-1)
{
System.out.print(ch);
}//while
}
}
键盘上输入的任何内容,写入到D:/data.dat中
public class TestKB {
public static void main(String[] args)
throws Exception
{
FileOutputStream fos=new FileOutputStream("D:/data.dat");
int ch;
while((ch=System.in.read())!=-1)
{
fos.write(ch);
}//while
fos.flush();
fos.close();
}
}
任何文件(字节文件)的复制
public class TestFIIO {
public static void main(String[] args)
throws Exception
{
FileInputStream fis=new FileInputStream("w:/1.jpg");
FileOutputStream fos=new FileOutputStream("d:/test.jpg");
int ch;
while((ch=fis.read())!=-1)
{
fos.write(ch);
}//while
fis.close();
fos.flush();
fos.close();
}
}
使用DataOutputStream类,完成:基于JAVA基本数据类型的写。
public class TestDOS {
public static void main(String[] args)
throws Exception
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("d:/t.dat"));
dos.writeInt(10);
for(int i=1;i<=10;i++)
{
dos.writeInt(i*3);
}
dos.writeInt(5);
for(int i=1;i<=5;i++)
{
dos.writeDouble(i*3D);
}
dos.flush();
dos.close();
}
}
使用DataInputStream类,完成:基于JAVA基本数据类型的读。
public class TestDio {
public static void main(String[] args)
throws Exception
{
DataInputStream dis=new DataInputStream(new FileInputStream("d:/t.dat"));
int len=dis.readInt();
System.out.println("Len:"+len);
for(int i=1;i<=len;i++)
{
int v=dis.readInt();
System.out.print(" "+v);
}
len=dis.readInt();
System.out.println("\n Double Len:"+len);
for(int i=1;i<=len;i++)
{
double d=dis.readDouble();
System.out.print(" "+d);
}
dis.close();
}
}
使用DataInputStream类,完成:在不知道数值总数的情况下,基于JAVA基本数据类型的读。
public class TestDio2 {
public static void main(String[] args)
throws Exception
{
DataInputStream dis=new DataInputStream(new FileInputStream("d:/t1.dat"));
try {
while(true)
{
int v=dis.readInt();
System.out.println(" "+v);
}
}catch (EOFException e) { }
dis.close();
}
}
24,使用File类,输出D:/目录下所有的内容。
File f=new File("d:/");
String[] fs=f.list();
for(String e:fs)
{
System.out.println(""+e);
}
25,使用File类,输出D:/目录下所有的文件名以.txt结尾的内容。
File f=new File("d:/");
//过滤器
String[] fs=f.list(
new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
}
);
System.out.println("==========");
for(String e:fs)
{
System.out.println(e);
}
以文件行的方式(使用 Bufferedreader类),输出文本文件d:/test.txt中内容;
BufferedReader br=new BufferedReader(new FileReader("d:/test.txt"));
String line=null;
while((line=br.readLine())!=null)
{
System.out.println(line);
}
br.close();
打开一个文本文件,输出其默认采用的编码。
FileReader fr=new FileReader("d:/test.txt");
System.out.println("编码:"+fr.getEncoding());
使用UTF-8编码,打开d:/test.txt文件,并输出其内容
InputStreamReader isr=new InputStreamReader(new FileInputStream("d:/test.txt"),
"UTF-8");
int ch1;
while((ch1=isr.read())!=-1)
{
System.out.print((char)ch1);
}
isr.close();
键盘上输入一行整数值,以 ,分隔。计算这些整数值的和。
br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一行整数值,以,分隔:");
line=br.readLine();
System.out.println(""+line);
String[] rs=line.split(",");
int sum=0;
for(String e:rs)
{
if(e.trim().length()>0)
{
int v=Integer.parseInt(e.trim());
sum += v;
}
}
System.out.println("sum="+sum);
使用PrintWriter类,向文件 d:/99.txt中输出99乘法表
public class P99 {
public static void main(String[] args)
throws Exception
{
PrintWriter pw=new PrintWriter(new FileWriter("d:/99.txt"));
for(int i=1;i<=9;i++)
{
for(int j=1;j<=i;j++)
{
pw.print(" "+i+"*"+j+"="+(i*j));
}//for--j
pw.println();//换行
}//for--i
pw.flush();
pw.close();
}//main
}
/**
运行结果:99.txt文件中内容:
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
**/
综合设计部分:
单例模式:只能创建一个实例
public class Singleton {
private Singleton(){
//.....
}
private static Singleton obj= new Singleton();
public static Singleton getObj()
{
return obj;
}
}
//饿汉式单例模式
public class HungryMan {
//可能会浪费空间
private byte[] buffer1 = new byte[1024*1024];
private byte[] buffer2 = new byte[1024*1024];
private byte[] buffer3 = new byte[1024*1024];
private byte[] buffer4 = new byte[1024*1024];
private HungryMan() {
}
private final static HungryMan HUNGRY_MAN = new HungryMan();
public static HungryMan getInstance(){
return HUNGRY_MAN;
}
}
package com.frans;
import javafx.scene.control.Tab;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
//懒汉式单例模式
public class LazyMan {
//红绿灯
private static boolean frans_fan = false;
private LazyMan() {
synchronized (LazyMan.class){
if(frans_fan == false){
frans_fan = true;
}else{
throw new RuntimeException("不要使用反射破坏单例");
}
/*
if(lazyMan != null){
throw new RuntimeException("不要使用反射破坏单例");
}*/
}
System.out.println(Thread.currentThread().getName() + "ok");
}
/**
* Java并发编程
* volatile关键字的两层语义
* 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
*
* 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
*
* 2)禁止进行指令重排序。
*/
private static volatile LazyMan lazyMan; //volatile防止指令重排。
//双重检测锁模式的懒汉式单例,DCL单例
public static LazyMan getInstance(){
//加锁
if(lazyMan == null){
synchronized (LazyMan.class){
if(lazyMan == null){
lazyMan = new LazyMan(); //不是原子操作
}
}
}
return lazyMan;
}
//反射可以破坏单例
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Field frans_fan = LazyMan.class.getDeclaredField("frans_fan");
frans_fan.setAccessible(true);
//LazyMan instance = LazyMan.getInstance();
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
LazyMan lazyMan = declaredConstructor.newInstance();
frans_fan.set(lazyMan, false);
LazyMan lazyMan1 = declaredConstructor.newInstance();
System.out.println(lazyMan);
System.out.println(lazyMan1);
}
/*
//多线程并发问题
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
LazyMan.getInstance();
}).start();
}
}*/
}
/**
* 1. 分配内存空间
* 2. 执行构造方法,初始化对象
* 3. 把这个对象指向这个空间
*
* 默认执行顺序 123
* 但是可能会出现 132 的执行顺序,此时lazyman还没有完成构造
*/
package com.frans;
//枚举
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public enum SingletonEnum {
INSTANCE;
public SingletonEnum getInstance(){
return INSTANCE;
}
}
class Test{
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
/*
SingletonEnum instance = SingletonEnum.INSTANCE;
SingletonEnum instance1 = SingletonEnum.INSTANCE;
System.out.println(instance);
System.out.println(instance1);
*/
SingletonEnum instance = SingletonEnum.INSTANCE;
Constructor<SingletonEnum> declaredConstructor = SingletonEnum.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
SingletonEnum instance1 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance1);
}
}