First Linked List in Java I just started learning Java, and wrote up a linked list. I'm coming from just having learned Haskell, so I've been out of the mindset of stateful computations for awhile.

I'd like to know how it could be improved in any way. Please be critical. Mainly though, I'd like suggestions on readability, and safe practices.

It's very simple right now, only allowing additions at the end and deletions; but I figured it would be sufficient for a review. 

class Node&lt;T&gt; {
    T cargo;
    Node&lt;T&gt; tail;

    public Node(T nCargo) {
        cargo = nCargo;
        tail = null;
    }

    public Node&lt;T&gt; getNext() {
        return tail;
    }

    public T getCargo() {
        return cargo;
    }

    public boolean isLast() {
        return tail == null;
    }

    public Node&lt;T&gt; getLast() {
        Node&lt;T&gt; curNode = this;
        while (!curNode.isLast()) {
            curNode = curNode.getNext();
        }
        return curNode;
    }

    public void add(T nCargo) {
        tail = new Node&lt;T&gt;(nCargo);
    }

    public boolean canLink() {
        return this.getNext().getNext() != null;
    }

    public void deleteNext() {
        if (this.canLink()) { tail = tail.getNext(); 
            } else { tail = null; }
    }

}

public class Vect&lt;T&gt; {
    Node&lt;T&gt; head;
    int vSize;

    public Vect() {
        head = null;
        vSize = 0;
    }
    public Vect(T cargo) {
        head = new Node&lt;T&gt;(cargo);
        vSize = 1;
    }

    public void pushBack(T cargo) {
        Node&lt;T&gt; last = head.getLast();
        vSize += 1;
        last.add(cargo);
    }

    private Node&lt;T&gt; getNodeAt(int i) {
        Node&lt;T&gt; curNode = head;
        for (int cI = 0; i &gt; cI; cI++) {
            curNode = curNode.getNext();
        }
        return curNode;
    }

    public T getAt(int i) {
        return getNodeAt(i).getCargo();
    }

    public int length() {
        return vSize;
    }

    public void deleteHead() {
        if (head.getNext() != null) { head = head.getNext();
            } else { head = null; }
        vSize -= 1;
    }

    public void deleteAt(int i) {
        if (i == 0) {
            deleteHead();
        } else {
            Node&lt;T&gt; curNode = this.getNodeAt(i - 1);
            curNode.deleteNext();
            vSize -= 1;
        }
    }
}


and its use:

public class Main {

    public static void main(String[] args) {
        Vect &lt;Integer&gt; v = new Vect&lt;Integer&gt;(2);
        v.pushBack(3);
        v.pushBack(4);
        v.pushBack(5);
        v.pushBack(6);

        for (int i = 0; i &lt; v.length(); ++i) {
            System.out.println(v.getAt(i));
        }

        v.deleteAt(2);

        for(int i = 0; i &lt; v.length(); ++i) {
            System.out.println(v.getAt(i));
        }

    }
}
Disclaimer: This review is reviewing this as work-in-process, and not as "finished".


On a quick glance this looks mostly correct. I still got a few points, that definitely need to be fixed before proceeding:


Index handling:
You don't do anything with negative indexes. vector.getAt(-1); results in an infinite loop, as well as vector.deleteAt(-1);. I suggest you just check and throw an InvalidArgumentException for any \$index &lt; 0\$ 
Empty list:
Your empty list throws null-pointer exceptions all around. Don't do that. You should check your head before doing stuff with it, and if it's null, throw IllegalStateException  or similar. 
Optimizing pushBack():
There is a relatively simple and quick-to-implement optimization for your pushBack. Your Vect&lt;T&gt; should maintain a "pointer" to the last node. On deleting the last node you need to check for the special-case just like when deleting head, but after that your pushBack becomes dead-simple:

 public void pushBack(T cargo) {
     tail.add(cargo);
     tail = tail.getNext();
     vSize++;
 }