JAVA入门学习实例

Java面向对象中类与对象的概念和使用

构造方法的主要作用 一是用来实例化该类。二是 让该类实例化的时候执行哪些方法,初始化哪些属性。当一个类声明了构造函数以后,JVM 是不会再给该类分配默认的构造函数。
构造方法是一种特殊的方法,具有以下特点。
(1)构造方法的方法名必须与类名相同。
(2)构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型。
(3)构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。
(4)构造方法不能由编程人员调用,而要系统调用。
(5)一个类可以定义多个构造方法,如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。
(6)构造方法可以重载,以参数的个数,类型,或排列顺序区分

重载与重写:
  重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数
  重写是子类的方法覆盖父类的方法,发生在继承中,要求方法名,参数类型和返回值都相同。被重写的方法不能拥有比父类更严格的权限(public>protected>default>private)

// Person.java
package com.example;

public class Person{
    String name;
    int age;
    public Person(String name,int age){    //构造方法
        this.name=name;
        this.age=age;
    }
    public Person(String name){  //方法重载,对参数类型或个数,权限均无要求
        this.name=name;
        System.out.println(name);

    }
    public void tell(){
        System.out.println(name +":" + age);
    }
}

// Main.java
import com.example.Person;

public class Main {
	public static void main(String[] args) {
		Person p =new Person("zhang",17);
		p.tell();
		Person q =new Person("Li"); // 实例化的时候调用重载构造方法
	}
}

Java面向对象的基本特征之封装性

封装就是隐藏实现细节,将属性私有化,提供公有方法访问私有属性。

// Person.java
package com.example;

public class Person{
	private String name;
	private int age;                //将类的成员变量声明为private
	public void setName(String name) {  //通过public的方法对变量进行访问
        this.name = name;       //一般定义两个方法实现这两种操作,即:setxx()与getxx()
	}
	public String getName() {
		return name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getAge() {
		return age;
	}
	public void tell(){
		System.out.println(getName() +":" + getAge());
	}
}

// Main.java
import com.example.Person;

public class Main {
	public static void main(String[] args) {
		Person p =new Person();
		p.setName("Zhang");
		p.setAge(17);
		p.tell();
	}
}

Java面向对象基本特征之继承

JAVA只支持单继承,一个类只能有一个父类,同时一个类可以实现多个接口,从而克服单继承的缺点。
子类不能直接访问父类private成员,可用set,get方法;
子对象的实例化过程先调用父类的构造方法,在调用子类的构造方法;
子类重写父类方法之后(方法名称,返回类型,参数都相同),不能拥有比父类更严格的访问权限(public>protected>default>private)
Super关键字强行执行父类方法
继承: class 子类 extends 父类{}

// Person.java
package com.example;

class Person{
	private String name;
	public void setName(String name) {    
		this.name = name;
	}
	public String getName() {
		return name;
	}
    public Person(int n){            //有参数的构造方法
        System.out.println("Person() constructor is called !");
    }
}

// Student.java
package com.example;

public class Student extends Person{            //继承
	private int score;
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public void tell() {
		System.out.println(getName() +": 得分"+getScore());
	}
	
	public Student() {               //构造方法的继承
		super(200);//构造方法先引用父类的构造方法,编译器找不到无参方法就报错.必须在子类构造方法最上面加一句super(int值)才可以通过编译.                
		System.out.println("Student() constructor is called !");
	}
}

// Main.java
import com.example.Student;

public class Main {
	public static void main(String[] args) {
    	Student s= new Student();
		s.setName("Zhang");
		s.setScore(100);
    	s.tell();
	}
}

Java面向对象基本特征之多态

什么是多态
  面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
  多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
  实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
  多态的作用:消除类型之间的耦合关系。
  现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。

下面是多态存在的三个必要条件,要求大家做梦时都能背出来!
多态存在的三个必要条件!
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。

多态的好处:
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。

//父类
class Father {
    //父类有一个打孩子方法 
    public void hitChild(){}
}
//子类1 
class Son1 extends Father {
    //重写父类打孩子方法 
    public void hitChild() {
        System.out.println("为什么打我?我做错什么了!");
    }
}
//子类2 
class Son2 extends Father{
    //重写父类打孩子方法 
    public void hitChild(){
        System.out.println("我知道错了,别打了!");
    }
}
//子类3 
class Son3 extends Father{
    //重写父类打孩子方法 
    public void hitChild(){
        System.out.println("我跑,你打不着!");
    }
}

//测试类 
public class Main {
    public static void main(String args[]){
        Father father;

        father = new Son1();
        father.hitChild();

        father = new Son2();
        father.hitChild();

        father = new Son3();
        father.hitChild();
    }
} 

Java面向对象-抽象类与接口

抽象类的特点:
1:包含一个抽象方法的类,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2:抽象方法只定义方法声明,并不定义方法实现。
3:抽象类不可以被创建对象(实例化)。
4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。子类必须重写抽象类中的所有抽象方法!

抽象类定义格式: abstract class className{属性;方法;抽象方法}

abstract class Person{
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public abstract void tell();
    public abstract void say();
}
class Student extends Person{
    public void tell(){
        System.out.println(getName());
    }
    public void say(){}; //子类必须重写抽象类中的所有抽象方法!
}
public class Main {
    public  static void main(String[] args) {
        Student s= new Student();
        s.setName("Zhang");
        s.tell();
    }
}

接 口:
1:是用关键字interface定义的特殊的类。里面全部由全局常量和公共的抽象方法组成。

interface Inter{
    全局常量:public static final
    抽象方法:public abstract
}

2:接口中有抽象方法,说明接口不可以实例化。接口的子类必须实现了接口中所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。子类必须重写抽象类中的所有抽象方法!
3:类与类之间存在着继承关系,类与接口中间存在的是实现关系。
    继承用extends ;实现用implements ;
4:接口和类不一样的地方,就是,接口可以被多实现,这就是多继承改良后的结果。java将多继承机制通过多实来体现。
5:一个类在继承另一个类的同时,还可以实现多个接口。所以接口的出现避免了单继承的局限性。还可以将类进行功能的扩展。

interface Inter1{
    public static final int num1 = 1;
    public abstract void tell();
}
interface Inter2{
    public static final int num2 = 2;
    public abstract void say();
}
//一个接口通过extends关键字同时继承多个接口
interface Inter3 extends Inter1,Inter2{
    public static final int num3 = 3;
    public abstract void call();
}
abstract class Abs{
    public abstract void print();
}
//通过子类实现接口
class A implements Inter1,Inter2 {
    public void tell(){
        System.out.println("A实现了接口" + num1);
    }

    public void say(){
        System.out.println("A实现了接口" + num2);
    }
}
//通过子类继承抽象类同时实现接口
class B extends Abs implements Inter3 {
    public void tell(){};
    public void say(){};
    public void call(){
        System.out.println("B实现了接口3,且继承了接口" + num1 + "," + num2);
    }
    public void print(){
        System.out.println("B继承抽象类Abs");
    }
}
public class Main {
    public  static void main(String[] args) {
        A a=new A();
        a.tell();
        a.say();
        B b=new B();
        b.print();
        b.call();
    }
}

Java面向对象-泛型

泛型是Java SE1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型类:

public class Main<T> {       //在类名后面添加了类型参数声明部分
    private T t;
    public void set(T t) {
        this.t = t;
    }
    public T get() {
        return t;
    }

    public static void main(String[] args) {
        Main<Integer> integerBox = new Main<Integer>();//对象创建:在类名后面添加具体类型
        Main<String> stringBox = new Main<String>();

        integerBox.set(new Integer(10));
        stringBox.set(new String("Hello World"));

        System.out.printf("Integer Value:%d\n", integerBox.get());
        System.out.printf("String Value:%s\n", stringBox.get());
    }
}

泛型方法将数组排序输出:

import java.util.Arrays;
public class Main {
    // 泛型方法 printArray
    public static <E> void printArray(E[] inputArray)
    {
        //排序
        Arrays.sort(inputArray);
        // 输出数组元素
        for (E element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println(); //换行
    }
    public static void main( String args[] ) {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 5, 3, 2, 5 };
        Double[] doubleArray = { 3.3, 2.2, 1.1, 4.4 };
        Character[] charArray = { 'C', 'A', 'E', 'B', 'D' };
        System.out.println( "Array integerArray contains:" );
        printArray(intArray); // 传递一个整型数组
        System.out.println( "Array doubleArray contains:" );
        printArray(doubleArray); // 传递一个双精度型数组
        System.out.println( "Array characterArray contains:" );
        printArray(charArray); // 传递一个字符型型数组
    }
}

Java集合类详解

Collection集合类的基本结构:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map (key----> value)
├Hashtable
├HashMap
└WeakHashMap

1、Collection接口
  Collection是最基本集合接口,它定义了一组允许重复的对象。Collection接口派生了两个子接口Set和List,分别定义了两种不同的存储方式。
2、 Set接口
  Set接口继承于Collection接口,它没有提供额外的方法, Set接口的集合类中的元素是不可的。但是可以排序。
  两个常用子类:
         1.散列存放:HashSet;
         2.有序存放:TreeSet;
3、 List接口
   List接口同样也继承于Collection接口,但是与Set接口恰恰相反,List接口的集合类中的元素是对象有序可重复
特征:有序且可重复。
  两个重要的实现类:ArrayList和LinkedList
  1.ArrayList特点是有序可重复的
  2.LinkedList是一个双向链表结构的。
4、Map接口
  Map也是接口,但没有继承Collection接口。该接口描述了从不重复的键到值的映射。Map接口用于维护键/值对(key/value pairs)。
  特征:它描述了从不重复的键到值的映射。
  两个重要的实现类:HashMap和TreeMap
  1.HashMap,中文叫散列表,基于哈希表实现,特点就是键值对的映射关系。一个key对应一个Value。HashMap中元素无序存放,Key不允许重复。更加适合于对元素进行插入、删除和定位。
  2.TreeMap,基于红黑书实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。
5、Iterator接口
  Iterator接口,在C#里有例外一种说法IEnumerator,他们都是集合访问器,用于循环访问集合中的对象。所有实现了Collection接口的容器类都有iterator方法,用于返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,Iterator接口方法能以迭代方式逐个访问集合中各个元素,并可以从Collection中除去适当的元素。
6、Comparable接口
  Comparable可以用于比较的实现,实现了Comparable接口的类可以通过实现comparaTo方法从而确定该类对象的排序方式。

List接口,Iterator接口:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        //添加元素
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add(null);
        //遍历
        for (String string : list) {
            System.out.println(string);
        }
        System.out.println("-------修改list--------");
        //修改
        list.set(1, "bbb2");
        //删除
        list.remove("ccc");
        //迭代器遍历
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("--------添加list-------");
        List<String> list2 = new ArrayList<String>();
        list2.add("a");
        list2.add("b");
        //将list2添加到list中
        list.addAll(list2);
        //遍历
        for (String string : list) {
            System.out.println(string);
        }
        System.out.println("清空前list的大小"+list.size());//打印大小
        list.clear(); //清空列表
        System.out.println("清空后list的大小"+list.size());//打印大小

    }
}

HashMap接口,set,collection,Iterator接口:

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<String,String>();
        map.put("1","A");
        map.put("2.5","B");
        map.put("123L","C");
        String str = map.get("1");
        System.out.println(str);
        System.out.println(map.size());
        System.out.println(map.containsKey("2.5"));
        System.out.println(map.containsValue("D"));

        //输出所有key
        Set<String> s = map.keySet();
        Iterator<String> i = s.iterator();
        while(i.hasNext()){
            System.out.println(i.next());
        }

        //输出所有value
        Collection<String> c = map.values();
        Iterator<String> j = c.iterator();
        while(j.hasNext()){
            System.out.println(j.next());
        }
    }}

Java本地文件操作

File类操作:

import java.io.*;
public class Main {

    public static void main(String[] args) {
        File folder = new File("E:\\new");
        folder.mkdirs();                  //创建文件夹
        System.out.println("文件夹创建成功");
        File folder1 = new File("E:\\test");
        folder.renameTo(folder1);         //重命名
        System.out.println("重命名成功");
        folder.delete();
        File file = new File("E:\\test\\d.txt");  //查找文件
        if(file.exists()){
            System.out.println(file.isFile());
            System.out.println(file.isDirectory());
        }else{
            System.out.println("文件不存在,马上进行创建!");
        }

        try {
            file.createNewFile();        //创建文件
        } catch (IOException e) {
            e.printStackTrace();
        }}}

Java中的IO操作

一:字节流
OutputStream和InputStream(基类)
FileOutputStream和FileInputStream(字节带缓冲输入、输出流)
BufferedInputStream和BufferedOutputStream(字节缓冲输入、输出流)

二:字符流
Reader和Writer(基类)
FileReader和FileWriter(定义字符输入、输出流)
BufferedReader和BufferedWriter(字符带缓冲输入、输出流)
LineNumberReader
IO操作:使用字节流读写数据

import java.io.*;
public class Main {
    public static void main(String[] args) {

        try {
            File file1 = new File("E:\\test\\input.txt" );
            file1.createNewFile();
            //输出流:向文件中写数据
            FileOutputStream fos=new FileOutputStream("E:\\test\\input.txt");
            String outString="HelloWorld";
            byte output[]=outString.getBytes("UTF-8");
            fos.write(output);

            //输入流:从文件中读取数据
            FileInputStream fis = new FileInputStream("E:\\test\\input.txt");
            byte input[]=new byte[20];
            fis.read(input);
            String s=new String(input,"UTF-8");
            System.out.println(s);

            //输出流:向另一文件中复制数据
            File file2 = new File("E:\\test\\output.txt" );
            file2.createNewFile();
            FileOutputStream fos1=new FileOutputStream("E:\\test\\output.txt");
            fos1.write(s.getBytes());
            fis.close();
            fos.close();
            fos1.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }}}		

带有缓冲的字符流读写数据:

import java.io.*;
public class Main {
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new  InputStreamReader(System.in));
        //BufferedReader对象创建后获取控制台输入流
        File file = new File("E:\\test\\output.txt");
        try {
            FileWriter fw = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fw);
            //加了一个缓冲,缓冲写满后再将数据写入硬盘 ,极大的提高了性能
            char[] cs = new char[50];
            br.read(cs);      //以使用read()方法从控制台读取一个字符
            String s = new String(cs);
            System.out.println(s.trim());
            bw.write(s); //将字符串写入磁盘文件中

            br.close();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Java多线程编程

一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。

Java提供了两种创建线程方法:
• 通过继承Thread类本身: class NewThread extends Thread{}
  new NewThread().start();
• 通过实现Runable接口: class NewThread implements Runnable{}
  new Thread( new NewThread()).start();
  继承Thread类和实现Runnable接口实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务。如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
  实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制(继承了Thread类就不能再继承其他类了)
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

通过继承Thread类本身创建线程:

class NewThread extends Thread {  //创建Thread的子类以控制线程的运行
    public NewThread(String name){
        super(name);               //调用父类构造方法给thread命名
    }
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Thread " + getName() + ":"+ i);
                Thread.sleep(50);        // 暂停线程,休眠
            }
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread.");
    }
}
public class Main {
    public static void main(String args[]) {
        NewThread t1=new NewThread("A");
        NewThread t2=new NewThread("B");
        NewThread t3=new NewThread("C");
        t1.start();
        t2.start();
        t3.start();
        System.out.println(t3.isAlive());//判断线程是否启动
    }
}

通过实现Runnable接口创建线程:

class NewThread implements Runnable {
    String name;
    public NewThread(String name){
        this.name=name;
    }
    public void run() {
        try {
            for(int i = 5; i > 0; i--) {
                System.out.println("Thread " + name + ":" + i);
                Thread.sleep(50);        // 暂停线程
            }
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread.");
    }
}
public class Main {
    public static void main(String args[]) {
        NewThread t1 = new NewThread("A");
        Thread demo = new Thread(t1);
        demo.start();

        for(int i = 0; i < 5; i++) {
            if(i > 1) {
                try {
                    demo.join();     //等待线程结束
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main 线程执行-->"+i);
        }
    }
}

线程同步:
  多线程环境中,可能存在多个线程同时使用某一资源造成资源冲突的情况(继承Thread类时)。多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。

例1:

class MyThread extends Thread {  //创建Thread的子类以控制线程的运行
    public MyThread(String name){
        super(name);
    }

    public void run() {
        while(true) {
            sale();
        }}
    private static int tickets = 30;
    public static synchronized void sale()  { //这里就是对函数进行同步。
        if(tickets > 0)  {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 剩余票数:"+ tickets);
        }
        tickets--;
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread t1 = new MyThread("窗口A");
        MyThread t2 = new MyThread("窗口B");
        MyThread t3 = new MyThread("窗口C");
        t1.start();
        t2.start();
        t3.start();
    }
}

例2:

public class Main implements Runnable{
    private int tickets = 10;
    public void run() {
        int count = 0;
        while(true) {
            synchronized(this) {
                if(tickets > -1) {
                    try {
                        Thread.sleep(100);
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    count = 10 - tickets;
                    System.out.println("当前有:" + tickets + " 张票"
                            + " ,售出:" + count + "张票"
                            + " ,售票员为:" + Thread.currentThread().getName());
                    tickets--;
                }else {
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        Main r = new Main();
        //调用Thread(Runnable threadOb,String threadName)构造方法.threadOb是一个实现Runnable 接口的类的实例,并且 threadName指定新线程的名字
        Thread t1 = new Thread(r,"张三");
        Thread t2 = new Thread(r,"李四");
        Thread t3 = new Thread(r,"王五");
        Thread t4 = new Thread(r,"赵六");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

Java中的Socket通信

Java socket通信已经被封装好了主要使用两个类ServerSocket 和Socket
首先写一个1v1的通信

Server:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
  public class GreetingServer
{
       // 设置端口号
       public static int portNo = 3333;
       public static void main(String[] args) throws IOException 
{
              ServerSocket s = new ServerSocket(portNo);
              System.out.println("The Server is start: " + s);
              // 阻塞,直到有客户端连接
        Socket socket = s.accept();
       try 
{              
     System.out.println("Accept the Client: " + socket);                   
 //设置IO句柄
 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);                    
		 while (true)
		{
                    String str = in.readLine();
                    if (str.equals("byebye"))
		{
                   break;
            }
            System.out.println("客户端发送的消息是: " + str);
                            out.println("服务器收到:"+str);
                     }
              } 
        finally 
{
                     System.out.println("close the Server socket and the io.");
                     socket.close();
                     s.close();
              }
    }
}

Client:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
 public class GreetingClient
 {
       static String clientName = "Mike";
       //端口号
public static int portNo = 3333;
       public static void main(String[] args) throws IOException
{
              // 设置连接地址类,连接本地
              InetAddress addr = InetAddress.getByName("localhost");        
              //要对应服务器端的3333端口号
              Socket socket = new Socket(addr, portNo);
              try
{
            System.out.println("socket = " + socket);
                     // 设置IO句柄
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(
New OutputStreamWriter(socket.getOutputStream())), true);
                     out.println("Hello Server,I am " + clientName);
                     String str = in.readLine();
                     System.out.println(str);
                     out.println("byebye");
              }
finally 
{
                     System.out.println("close the Client socket and the io.");
                     socket.close();
        }
       }
}

通过程序里引入多线程的机制,可让一个服务器端同时监听并接收多个客户端的请求,并同步地为它们提供通讯服务。
  基于多线程的通讯方式,将大大地提高服务器端的利用效率,并能使服务器端能具备完善的服务功能。

Server:

package tcp;
import java.io.*;
import java.net.*;
//第二步,由于我们在服务器端引入线程机制,所以我们要编写线程代码的主体执行类ServerThreadCode,这个类的代码如下所示:
class ServerThreadCode extends Thread 
{
       //客户端的socket
       private Socket clientSocket;
       //IO句柄
       private BufferedReader sin;
       private PrintWriter sout;    
       //默认的构造函数
       public ServerThreadCode()
       {}  
       public ServerThreadCode(Socket s) throws IOException 
       {
              clientSocket = s;            
              //初始化sin和sout的句柄
              sin = new BufferedReader(new InputStreamReader(clientSocket
                            .getInputStream()));
        sout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                            clientSocket.getOutputStream())), true);             
              //开启线程
              start(); 
       }
       //线程执行的主体函数
       public void run() 
       {
              try 
              {
                     //用循环来监听通讯内容
                     for(;;) 
                     {
                String str = sin.readLine();
                            //如果接收到的是byebye,退出本次通讯
                            if (str.equals("byebye"))
                            {     
                                   break;
                            }     
                            System.out.println("In Server reveived the info: " + str);
                            sout.println(str);
                     }
                     System.out.println("closing the server socket!");
              } 
        catch (IOException e) 
              {
                     e.printStackTrace();
              } 
              finally 
              {
                     System.out.println("close the Server socket and the io.");
                     try 
            {
                            clientSocket.close();
                     } 
                     catch (IOException e) 
                     {
                            e.printStackTrace();
                     }
              }
       }
}
public class ThreadServer 
{
       //端口号
       static final int portNo = 3333;
       public static void main(String[] args) throws IOException 
       {
              //服务器端的socket
              ServerSocket s = new ServerSocket(portNo);
              System.out.println("The Server is start: " + s);      
              try 
              {
                     for(;;)                          
                     {
                  //阻塞,直到有客户端连接
                            Socket socket = s.accept();
                            //通过构造函数,启动线程
                        new ServerThreadCode(socket);
                     }
              }
           finally 
              {
                     s.close();
              }
       }
}

Client:

package tcp;
import java.net.*;
import java.io.*;
//第二步,编写线程执行主体的ClientThreadCode类,同样,这个类通过继承Thread来实现线程的功能。
class ClientThreadCode extends Thread 
{
  //客户端的socket
  private Socket socket;    
  //线程统计数,用来给线程编号
  private static int cnt = 0;
  private int clientId = cnt++;
  private BufferedReader in;
  private PrintWriter out;
  //构造函数
  public ClientThreadCode(InetAddress addr) 
  {
    try 
    {
      socket = new Socket(addr, 3333);
    }
    catch(IOException e) 
    {
          e.printStackTrace();
    }
    //实例化IO对象
try 
    {    
      in = new BufferedReader(
             new InputStreamReader(socket.getInputStream()));    
       out = new PrintWriter(
               new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
        //开启线程
        start();
     } 
     catch(IOException e) 
     {
        //出现异常,关闭socket 
          try 
          {
            socket.close();
        } 
          catch(IOException e2) 
          {
              e2.printStackTrace();       
          }
     }
  }  
  //线程主体方法
public void run() 
  {
    try 
    {
      out.println("Hello Server,My id is " + clientId );
      String str = in.readLine();
      System.out.println(str);
      out.println("byebye");
    } 
    catch(IOException e) 
    {
       e.printStackTrace();  
    }
    finally 
    {
      try 
      {
        socket.close();
      } 
      catch(IOException e) 
      {
              e.printStackTrace();
      }    
    }
  }
}
//第三步,编写客户端的主体代码,在这段代码里,将通过for循环,根据指定的待创建的线程数量,通过ClientThreadCode的构造函数,创建若干个客户端线程,同步地和服务器端通讯。
public class ThreadClient 
{
  public static void main(String[] args) 
      throws IOException, InterruptedException 
  {
    int threadNo = 0;
       InetAddress addr = 
       InetAddress.getByName("localhost");
    for(threadNo = 0;threadNo<3;threadNo++)
    {
       new ClientThreadCode(addr);
    }
  }
}

Java中的反射

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

一个简单的例子:

public class Apple {

    private int price;

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public static void main(String[] args) throws Exception{
        //正常的调用
        Apple apple = new Apple();
        apple.setPrice(5);
        System.out.println("Apple Price:" + apple.getPrice());
        //使用反射调用
        Class clz = Class.forName("com.chenshuyi.api.Apple");         // 获取类的 Class 对象实例, 也可以使用类对象的 getClass() 方法:apple.getClass();
        Method setPriceMethod = clz.getMethod("setPrice", int.class);
        Constructor appleConstructor = clz.getConstructor();     // 根据 Class 对象实例获取 Constructor 对象
        Object appleObj = appleConstructor.newInstance();       // 使用 Constructor 对象的 newInstance 方法获取反射类对象, 也可以通过 Class 对象的 newInstance() 方法:clz.newInstance();
        setPriceMethod.invoke(appleObj, 14);                     // 利用 invoke 方法调用方法
        Method getPriceMethod = clz.getMethod("getPrice");
        System.out.println("Apple Price:" + getPriceMethod.invoke(appleObj));
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值